# -*- coding: utf-8 -*-
"""Route tests for mid-section defect APIs."""

from __future__ import annotations

from unittest.mock import patch

import mes_dashboard.core.database as db
from mes_dashboard.app import create_app
from mes_dashboard.core.rate_limit import reset_rate_limits_for_tests


def _client():
    db._ENGINE = None
    app = create_app('testing')
    app.config['TESTING'] = True
    return app.test_client()


def setup_function():
    reset_rate_limits_for_tests()


def teardown_function():
    reset_rate_limits_for_tests()


@patch('mes_dashboard.routes.mid_section_defect_routes.query_analysis')
def test_analysis_success(mock_query_analysis):
    mock_query_analysis.return_value = {
        'kpi': {'total_input': 100},
        'charts': {'by_station': []},
        'daily_trend': [],
        'available_loss_reasons': ['A'],
        'genealogy_status': 'ready',
        'detail': [{}, {}],
    }

    client = _client()
    response = client.get(
        '/api/mid-section-defect/analysis?start_date=2025-01-01&end_date=2025-01-31&loss_reasons=A,B'
    )

    assert response.status_code == 200
    payload = response.get_json()
    assert payload['success'] is True
    assert payload['data']['detail_total_count'] == 2
    assert payload['data']['kpi']['total_input'] == 100
    mock_query_analysis.assert_called_once_with('2025-01-01', '2025-01-31', ['A', 'B'])


def test_analysis_missing_dates_returns_400():
    client = _client()
    response = client.get('/api/mid-section-defect/analysis?start_date=2025-01-01')

    assert response.status_code == 400
    payload = response.get_json()
    assert payload['success'] is False


@patch('mes_dashboard.routes.mid_section_defect_routes.query_analysis')
def test_analysis_service_failure_returns_500(mock_query_analysis):
    mock_query_analysis.return_value = None

    client = _client()
    response = client.get('/api/mid-section-defect/analysis?start_date=2025-01-01&end_date=2025-01-31')

    assert response.status_code == 500
    payload = response.get_json()
    assert payload['success'] is False


@patch('mes_dashboard.routes.mid_section_defect_routes.query_analysis')
@patch('mes_dashboard.core.rate_limit.check_and_record', return_value=(True, 7))
def test_analysis_rate_limited_returns_429(_mock_rate_limit, mock_query_analysis):
    client = _client()
    response = client.get('/api/mid-section-defect/analysis?start_date=2025-01-01&end_date=2025-01-31')

    assert response.status_code == 429
    assert response.headers.get('Retry-After') == '7'
    payload = response.get_json()
    assert payload['error']['code'] == 'TOO_MANY_REQUESTS'
    mock_query_analysis.assert_not_called()


@patch('mes_dashboard.routes.mid_section_defect_routes.query_analysis_detail')
def test_detail_success(mock_query_detail):
    mock_query_detail.return_value = {
        'detail': [{'CONTAINERNAME': 'LOT-1'}],
        'pagination': {'page': 2, 'page_size': 200, 'total_count': 350, 'total_pages': 2},
    }

    client = _client()
    response = client.get(
        '/api/mid-section-defect/analysis/detail?start_date=2025-01-01&end_date=2025-01-31&page=2&page_size=200'
    )

    assert response.status_code == 200
    payload = response.get_json()
    assert payload['success'] is True
    assert payload['data']['pagination']['page'] == 2
    mock_query_detail.assert_called_once_with(
        '2025-01-01',
        '2025-01-31',
        None,
        page=2,
        page_size=200,
    )


def test_detail_missing_dates_returns_400():
    client = _client()
    response = client.get('/api/mid-section-defect/analysis/detail?end_date=2025-01-31')

    assert response.status_code == 400
    payload = response.get_json()
    assert payload['success'] is False


@patch('mes_dashboard.routes.mid_section_defect_routes.query_analysis_detail')
@patch('mes_dashboard.core.rate_limit.check_and_record', return_value=(True, 5))
def test_detail_rate_limited_returns_429(_mock_rate_limit, mock_query_detail):
    client = _client()
    response = client.get('/api/mid-section-defect/analysis/detail?start_date=2025-01-01&end_date=2025-01-31')

    assert response.status_code == 429
    assert response.headers.get('Retry-After') == '5'
    payload = response.get_json()
    assert payload['error']['code'] == 'TOO_MANY_REQUESTS'
    mock_query_detail.assert_not_called()


@patch('mes_dashboard.routes.mid_section_defect_routes.export_csv')
def test_export_success(mock_export_csv):
    mock_export_csv.return_value = iter([
        '\ufeff',
        'LOT ID,TYPE\r\n',
        'A001,T1\r\n',
    ])

    client = _client()
    response = client.get(
        '/api/mid-section-defect/export?start_date=2025-01-01&end_date=2025-01-31&loss_reasons=A,B'
    )

    assert response.status_code == 200
    assert 'text/csv' in response.content_type
    assert 'attachment;' in response.headers.get('Content-Disposition', '')
    mock_export_csv.assert_called_once_with('2025-01-01', '2025-01-31', ['A', 'B'])


@patch('mes_dashboard.routes.mid_section_defect_routes.export_csv')
@patch('mes_dashboard.core.rate_limit.check_and_record', return_value=(True, 9))
def test_export_rate_limited_returns_429(_mock_rate_limit, mock_export_csv):
    client = _client()
    response = client.get('/api/mid-section-defect/export?start_date=2025-01-01&end_date=2025-01-31')

    assert response.status_code == 429
    assert response.headers.get('Retry-After') == '9'
    payload = response.get_json()
    assert payload['error']['code'] == 'TOO_MANY_REQUESTS'
    mock_export_csv.assert_not_called()
