from __future__ import annotations

import json
from dataclasses import dataclass
from datetime import timezone
from pathlib import Path

from django.core.management.base import BaseCommand, CommandError

from apps.ocpp import store
from apps.ocpp.transactions_io import import_transactions_deduped


@dataclass
class ReplayResult:
    imported: int
    skipped: int
    session_log_written: bool


class Command(BaseCommand):
    help = "Replay an extracted OCPP transaction into the system"

    def add_arguments(self, parser) -> None:
        parser.add_argument(
            "extract",
            help="Path to extract JSON generated by ocpp_extract --out",
        )

    def handle(self, *args, **options) -> None:
        extract_path = Path(options["extract"])
        if not extract_path.exists():
            raise CommandError(f"Extract file not found: {extract_path}")

        data = json.loads(extract_path.read_text(encoding="utf-8"))
        result = self._replay(data)
        self.stdout.write(
            self.style.SUCCESS(
                f"Imported {result.imported} transaction(s), "
                f"skipped {result.skipped} duplicate(s)."
            )
        )
        if result.session_log_written:
            self.stdout.write(self.style.SUCCESS("Session log restored."))

    def _replay(self, data: dict) -> ReplayResult:
        if data.get("format") != "ocpp-extract-v1":
            raise CommandError("Unsupported extract format.")

        imported, skipped, imported_transactions = import_transactions_deduped(
            {"chargers": data.get("chargers", []), "transactions": data.get("transactions", [])}
        )

        session_log_written = False
        session_entries = data.get("session_log", [])
        if imported_transactions and session_entries:
            tx = imported_transactions[0]
            session_path = self._session_log_path(tx)
            if not session_path.exists():
                session_path.write_text(
                    json.dumps(session_entries, indent=2, ensure_ascii=False) + "\n",
                    encoding="utf-8",
                )
                session_log_written = True

        return ReplayResult(
            imported=imported, skipped=skipped, session_log_written=session_log_written
        )

    def _session_log_path(self, tx) -> Path:
        start_time = tx.start_time
        if start_time.tzinfo is None:
            start_time = start_time.replace(tzinfo=timezone.utc)
        date = start_time.astimezone(timezone.utc).strftime("%Y%m%d")
        if not tx.charger:
            folder = store._session_folder(store.AGGREGATE_SLUG)
        else:
            key = store.identity_key(tx.charger.charger_id, tx.connector_id)
            folder = store._session_folder(key)
        return folder / f"{date}_{tx.pk}.json"
