from __future__ import annotations

import json
from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np

from m3m_twin.envelope import minimum_altitude_for_speed_m, mission_envelope
from m3m_twin.io import sha256_file, write_csv, write_json
from m3m_twin.srf import ZENODO_RECORD, fetch_and_analyse_responses


ROOT = Path(__file__).resolve().parent
OUTPUT = ROOT / "outputs" / "focused"
FIGURES = ROOT / "outputs" / "figures"


def main() -> None:
    OUTPUT.mkdir(parents=True, exist_ok=True)
    FIGURES.mkdir(parents=True, exist_ok=True)

    response_rows, curves = fetch_and_analyse_responses()
    write_csv(OUTPUT / "m3m-spectral-response-summary.csv", response_rows, list(response_rows[0]))
    response_receipt = {
        "schemaVersion": 1,
        "status": "PASSED",
        "source": ZENODO_RECORD,
        "sourceLicense": "CC BY 4.0",
        "sourceAccessedOn": "2026-08-04",
        "rawThirdPartyFilesRedistributed": False,
        "method": "SHA-256 verified download; trapezoidal response-weighted wavelength; linearly interpolated FWHM",
        "bands": response_rows,
        "claimBoundary": (
            "Measured filter responses characterize spectral sensitivity only. They do not establish crop, "
            "disease, radiometric, or field accuracy."
        ),
    }
    write_json(OUTPUT / "m3m-spectral-response-receipt.json", response_receipt)

    palette = {"green": "#3f8f47", "red": "#c63b32", "red_edge": "#8a4ea3", "nir": "#303f70"}
    labels = {"green": "Green", "red": "Red", "red_edge": "Red edge", "nir": "NIR"}
    fig, ax = plt.subplots(figsize=(10.2, 5.3), constrained_layout=True)
    for band, (wavelength, response) in curves.items():
        ax.plot(wavelength, response, lw=2.1, color=palette[band], label=labels[band])
    ax.set(
        xlabel="Wavelength (nm)", ylabel="Normalized response",
        title="Measured DJI Mavic 3M multispectral response functions",
        xlim=(520, 910), ylim=(-0.02, 1.06),
    )
    ax.grid(alpha=0.22)
    ax.legend(ncol=4, loc="upper center")
    ax.text(
        0.01, -0.23,
        "Derived from Atherton et al., Zenodo 11102543 (CC BY 4.0); raw CSV files are not redistributed.",
        transform=ax.transAxes, fontsize=8, color="#555555",
    )
    fig.savefig(FIGURES / "figure-5-measured-spectral-response.png", dpi=200, bbox_inches="tight")
    plt.close(fig)

    envelope_rows = mission_envelope()
    write_csv(OUTPUT / "mission-feasibility-envelope.csv", envelope_rows, list(envelope_rows[0]))
    altitudes = sorted({float(row["altitudeAglM"]) for row in envelope_rows})
    overlaps = sorted({float(row["frontOverlapPct"]) for row in envelope_rows})
    mission_minutes = np.array([
        [next(float(row["estimatedMissionMinutes"]) for row in envelope_rows
              if row["altitudeAglM"] == altitude and row["frontOverlapPct"] == overlap)
         for overlap in overlaps]
        for altitude in altitudes
    ])
    max_speeds = np.array([
        [next(float(row["triggerLimitedMaxSpeedMS"]) for row in envelope_rows
              if row["altitudeAglM"] == altitude and row["frontOverlapPct"] == overlap)
         for overlap in overlaps]
        for altitude in altitudes
    ])
    fig, axes = plt.subplots(1, 2, figsize=(11.2, 5.0), constrained_layout=True)
    image = axes[0].imshow(mission_minutes, origin="lower", aspect="auto", cmap="YlOrBr")
    axes[0].set_title("Estimated mission time (min)")
    fig.colorbar(image, ax=axes[0], fraction=0.047)
    image2 = axes[1].imshow(max_speeds, origin="lower", aspect="auto", cmap="YlGnBu")
    axes[1].set_title("2 s cadence-limited max speed (m/s)")
    fig.colorbar(image2, ax=axes[1], fraction=0.047)
    for ax in axes:
        ax.set_xticks(range(len(overlaps)), [f"{value:.0f}%" for value in overlaps])
        ax.set_yticks(range(len(altitudes)), [f"{value:.0f}" for value in altitudes])
        ax.set_xlabel("Forward overlap target")
        ax.set_ylabel("Altitude AGL (m)")
    for row_index in range(len(altitudes)):
        for column_index in range(len(overlaps)):
            mission_colour = "white" if mission_minutes[row_index, column_index] >= 80 else "black"
            speed_colour = "white" if max_speeds[row_index, column_index] >= 12 else "black"
            axes[0].text(
                column_index, row_index, f"{mission_minutes[row_index, column_index]:.1f}",
                ha="center", va="center", fontsize=7, color=mission_colour,
            )
            axes[1].text(
                column_index, row_index, f"{max_speeds[row_index, column_index]:.1f}",
                ha="center", va="center", fontsize=7, color=speed_colour,
            )
    fig.suptitle("Virtual 12 ha field: resolution, overlap, cadence and time trade-offs", fontsize=13)
    fig.text(
        0.5, -0.015,
        "Cadence limits are not safe-flight speeds; values above 15 m/s exceed the official normal-mode maximum.",
        ha="center", fontsize=8, color="#555555",
    )
    fig.savefig(FIGURES / "figure-6-mission-feasibility-envelope.png", dpi=200, bbox_inches="tight")
    plt.close(fig)

    sixty_rows = [row for row in envelope_rows if row["altitudeAglM"] == 60]
    payload = {
        "schemaVersion": 1,
        "status": "PASSED",
        "reportNumber": "SHWRP-2026-034",
        "revision": "v1.1",
        "sourceAccessedOn": "2026-08-04",
        "measuredSpectralResponseBands": len(response_rows),
        "missionEnvelopeScenarioCount": len(envelope_rows),
        "minimumAglForFiveMetresPerSecondAt80PctOverlapM": round(
            minimum_altitude_for_speed_m(5.0, 80.0), 3
        ),
        "sixtyMetreFrontOverlapScenarios": sixty_rows,
        "fieldFlightExecuted": False,
        "realMavic3MImagesProcessed": False,
        "diseaseDiagnosisValidated": False,
        "generatedFiles": [],
        "claimBoundary": (
            "This revision adds measured filter-response analysis and a synthetic mission envelope. "
            "It remains an engineering study without aircraft connection, field flight, real image processing, "
            "ground truth, agronomic diagnosis, safe-flight authorization, or legal determination."
        ),
    }
    generated = [
        OUTPUT / "m3m-spectral-response-summary.csv",
        OUTPUT / "m3m-spectral-response-receipt.json",
        OUTPUT / "mission-feasibility-envelope.csv",
        FIGURES / "figure-5-measured-spectral-response.png",
        FIGURES / "figure-6-mission-feasibility-envelope.png",
    ]
    payload["generatedFiles"] = [
        {"path": path.relative_to(ROOT).as_posix(), "bytes": path.stat().st_size, "sha256": sha256_file(path)}
        for path in generated
    ]
    write_json(OUTPUT / "focused-analysis-receipt.json", payload)
    print(json.dumps(payload, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
