from __future__ import annotations

from datetime import date
from types import SimpleNamespace
from unittest.mock import patch
import uuid

from django.test import override_settings

from farm_data.models import SensorData
from integration_tests.base import IntegrationAPITestCase
from location_data.models import AnalysisGridCell, AnalysisGridObservation, RemoteSensingRun


@override_settings(ROOT_URLCONF="integration_tests.location_data_urls")
class RemoteSensingApiFlowTests(IntegrationAPITestCase):
    def setUp(self) -> None:
        super().setUp()
        self.farm_uuid = uuid.UUID("11111111-1111-1111-1111-111111111111")
        self.farm = SensorData.objects.create(
            farm_uuid=self.farm_uuid,
            center_location=self.primary_location,
            sensor_payload={},
        )
        self.temporal_end = date(2026, 5, 9)
        self.temporal_start = date(2026, 4, 9)

    @patch("location_data.views.timezone.localdate", return_value=date(2026, 5, 10))
    @patch("location_data.views.run_remote_sensing_analysis_task.delay")
    def test_remote_sensing_post_and_status_flow(self, mock_delay, _mock_localdate) -> None:
        task_id = uuid.UUID("9e7f3aaa-6d34-4428-a196-478af7a2d7f6")
        mock_delay.return_value = SimpleNamespace(id=str(task_id))

        enqueue_response = self.client.post(
            "/api/location-data/remote-sensing/",
            data={
                "farm_uuid": str(self.farm_uuid),
                "force_refresh": False,
            },
            format="json",
        )

        self.assertEqual(enqueue_response.status_code, 202, enqueue_response.json())
        enqueue_payload = enqueue_response.json()["data"]
        self.assertEqual(enqueue_payload["status"], "processing")
        self.assertEqual(enqueue_payload["source"], "processing")
        self.assertEqual(enqueue_payload["task_id"], str(task_id))
        self.assertEqual(enqueue_payload["temporal_extent"]["start_date"], "2026-04-09")
        self.assertEqual(enqueue_payload["temporal_extent"]["end_date"], "2026-05-09")

        run = RemoteSensingRun.objects.get(pk=enqueue_payload["run"]["id"])
        self.assertEqual(run.status, RemoteSensingRun.STATUS_PENDING)
        self.assertEqual(run.temporal_start, self.temporal_start)
        self.assertEqual(run.temporal_end, self.temporal_end)
        self.assertEqual(run.metadata["task_id"], str(task_id))
        mock_delay.assert_called_once()

        status_response = self.client.get(f"/api/location-data/remote-sensing/runs/{task_id}/status/")
        self.assertEqual(status_response.status_code, 200, status_response.json())
        status_payload = status_response.json()["data"]
        self.assertEqual(status_payload["status"], "pending")
        self.assertEqual(status_payload["run"]["pipeline_status"], "pending")

        cell = AnalysisGridCell.objects.create(
            soil_location=self.primary_location,
            block_code="",
            cell_code="cell-1",
            chunk_size_sqm=900,
            geometry=self.primary_boundary,
            centroid_lat=f"{self.primary_lat:.6f}",
            centroid_lon=f"{self.primary_lon:.6f}",
        )
        AnalysisGridObservation.objects.create(
            cell=cell,
            run=run,
            temporal_start=self.temporal_start,
            temporal_end=self.temporal_end,
            ndvi=0.61,
            ndwi=0.22,
            soil_vv=0.13,
            soil_vv_db=-8.860566,
            dem_m=1550.0,
            slope_deg=4.2,
            metadata={"backend_name": "openeo"},
        )
        run.status = RemoteSensingRun.STATUS_SUCCESS
        run.metadata = {**(run.metadata or {}), "stage": "completed", "selected_features": ["ndvi", "ndwi"]}
        run.save(update_fields=["status", "metadata", "updated_at"])

        completed_response = self.client.get(f"/api/location-data/remote-sensing/runs/{task_id}/status/")
        self.assertEqual(completed_response.status_code, 200, completed_response.json())
        completed_payload = completed_response.json()["data"]
        self.assertEqual(completed_payload["status"], "completed")
        self.assertEqual(completed_payload["summary"]["cell_count"], 1)
        self.assertEqual(completed_payload["summary"]["ndvi_mean"], 0.61)
        self.assertEqual(len(completed_payload["cells"]), 1)
        self.assertEqual(completed_payload["cells"][0]["cell_code"], "cell-1")
