from django.test import TestCase, override_settings

from location_data.grid_analysis import create_or_get_analysis_grid_cells
from location_data.models import AnalysisGridCell, BlockSubdivision, SoilLocation


@override_settings(SUBDIVISION_CHUNK_SQM=900)
class AnalysisGridServiceTests(TestCase):
    def setUp(self):
        self.boundary = {
            "type": "Polygon",
            "coordinates": [
                [
                    [51.389000, 35.689000],
                    [51.389760, 35.689000],
                    [51.389760, 35.689620],
                    [51.389000, 35.689620],
                    [51.389000, 35.689000],
                ]
            ],
        }
        self.location = SoilLocation.objects.create(
            latitude="35.689310",
            longitude="51.389380",
            farm_boundary=self.boundary,
        )
        self.location.set_input_block_count(1)
        self.location.save(update_fields=["input_block_count", "block_layout", "updated_at"])
        self.subdivision = BlockSubdivision.objects.create(
            soil_location=self.location,
            block_code="block-1",
            source_boundary=self.boundary,
            chunk_size_sqm=900,
            status="created",
        )

    def test_create_analysis_grid_cells_persists_30x30_cells(self):
        result = create_or_get_analysis_grid_cells(
            self.location,
            block_code="block-1",
            block_subdivision=self.subdivision,
        )

        self.assertTrue(result["created"])
        self.assertEqual(result["chunk_size_sqm"], 900)
        self.assertGreater(result["created_count"], 0)
        self.assertEqual(result["created_count"], result["total_count"])

        cells = list(
            AnalysisGridCell.objects.filter(
                soil_location=self.location,
                block_code="block-1",
                chunk_size_sqm=900,
            ).order_by("cell_code")
        )
        self.assertEqual(len(cells), result["total_count"])
        self.assertTrue(all(cell.block_subdivision_id == self.subdivision.id for cell in cells))
        self.assertTrue(all(cell.geometry.get("type") == "Polygon" for cell in cells))
        self.assertTrue(all(len(cell.geometry.get("coordinates", [[]])[0]) == 5 for cell in cells))

        self.subdivision.refresh_from_db()
        self.location.refresh_from_db()
        self.assertEqual(
            self.subdivision.metadata["analysis_grid"]["chunk_size_sqm"],
            900,
        )
        self.assertEqual(
            self.subdivision.metadata["analysis_grid"]["cell_count"],
            result["total_count"],
        )
        self.assertEqual(
            self.location.block_layout["blocks"][0]["analysis_grid_summary"]["chunk_size_sqm"],
            900,
        )

    def test_create_analysis_grid_cells_is_idempotent(self):
        first = create_or_get_analysis_grid_cells(
            self.location,
            block_code="block-1",
            block_subdivision=self.subdivision,
        )
        second = create_or_get_analysis_grid_cells(
            self.location,
            block_code="block-1",
            block_subdivision=self.subdivision,
        )

        self.assertTrue(first["created"])
        self.assertFalse(second["created"])
        self.assertEqual(second["created_count"], 0)
        self.assertEqual(second["existing_count"], first["total_count"])
        self.assertEqual(
            AnalysisGridCell.objects.filter(
                soil_location=self.location,
                block_code="block-1",
                chunk_size_sqm=900,
            ).count(),
            first["total_count"],
        )

    def test_create_analysis_grid_cells_uses_location_boundary_without_subdivision(self):
        result = create_or_get_analysis_grid_cells(
            self.location,
            block_code="",
        )

        self.assertGreater(result["total_count"], 0)
        self.assertTrue(
            AnalysisGridCell.objects.filter(
                soil_location=self.location,
                block_code="",
                chunk_size_sqm=900,
            ).exists()
        )
