import { useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import {
  getInspection,
  patchInspection,
  createMarker,
  deleteMarker,
  type MarkerSummary,
} from "@/api/inspections";
import { uploadPhoto, uploadPhotoAnnotation } from "@/api/photos";
import { PhotoSlot } from "@/components/camera/PhotoSlot";
import { CameraCapture } from "@/components/camera/CameraCapture";
import { VendorVehicleScheme } from "@/components/vehicle-scheme/VendorVehicleScheme";
import { TireWearDialog } from "@/components/inspection/TireWearDialog";
import { ZoneConfirmDialog } from "@/components/damage-flow/ZoneConfirmDialog";
import { ZoneDetailView } from "@/components/damage-flow/ZoneDetailView";
import { DamageClassifyDialog } from "@/components/damage-flow/DamageClassifyDialog";
import { PhotoAnnotateStep } from "@/components/damage-flow/PhotoAnnotateStep";
import { AuthImg } from "@/components/AuthImg";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { loadZoneLabels } from "@/data/zoneLabels";
import { damageTypeRuToEnum } from "@/data/damageVocabulary";
import { ttImageUrl } from "@/api/vehicles";

// Слоты фото осмотра — в @/lib/inspectionSlots (покрыто тестами).
import { slotsForType } from "@/lib/inspectionSlots";

const SEVERITY_LABELS: Record<string, string> = {
  cosmetic: "косметика",
  minor: "лёгкое",
  moderate: "среднее",
  severe: "тяжёлое",
};

const DAMAGE_TYPE_LABELS: Record<string, string> = {
  damaged: "повреждено",
  scratch: "царапина",
  chip: "скол",
  dent: "вмятина",
  crack: "трещина",
  scuff: "затёртость",
  burn: "прожог",
  stain: "пятно",
  bent: "погнуто",
  torn: "порвано",
  cut: "порез",
  puncture: "прокол",
  bulge: "грыжа",
  missing: "отсутствует",
  removed: "снято",
  "not-working": "не работает",
};

// Vendor 3-position severity index → backend literal
const SEVERITY_MAP = ["minor", "moderate", "severe"] as const;

function humanizeMarkerSide(
  side: string | null | undefined,
  zoneLabels?: Record<string, string> | null,
): string {
  if (!side) return "—";
  if (side === "tires") return "Резина";
  const zm = /^zone-(\d+)$/.exec(side);
  if (zm) {
    const label = zoneLabels?.[zm[1]];
    if (label) return label;
    return `Зона ${zm[1]}`;
  }
  const map: Record<string, string> = {
    top: "Сверху",
    front: "Перед",
    back: "Зад",
    left: "Левый",
    right: "Правый",
    "bumper-fl": "Бампер ПЛ",
    "bumper-fr": "Бампер ПП",
    "bumper-rl": "Бампер ЗЛ",
    "bumper-rr": "Бампер ЗП",
    // Legacy named zone-* support (data from earlier prod)
    "zone-front": "Передний бампер",
    "zone-rear": "Задний бампер",
    "zone-left": "Левый бок",
    "zone-right": "Правый бок",
    "zone-hood": "Капот",
    "zone-trunk": "Багажник",
    "zone-roof": "Крыша",
  };
  return map[side] ?? side;
}

type DamageFlow =
  | { kind: "idle" }
  | { kind: "confirm"; zoneId: number; zoneLabel: string }
  | { kind: "placePoints"; zoneId: number; zoneLabel: string }
  | { kind: "classify"; zoneId: number; zoneLabel: string; points: { x: number; y: number }[] }
  | { kind: "capture"; zoneId: number; zoneLabel: string; points: { x: number; y: number }[]; damageType: string; severity: 0 | 1 | 2 }
  | { kind: "annotate"; zoneId: number; zoneLabel: string; points: { x: number; y: number }[]; damageType: string; severity: 0 | 1 | 2; photoFile: File };

export default function InspectionEditor() {
  const { id } = useParams<{ id: string }>();
  const insId = Number(id);
  const navigate = useNavigate();
  const qc = useQueryClient();

  const [flow, setFlow] = useState<DamageFlow>({ kind: "idle" });
  const [zoneLabels, setZoneLabels] = useState<Record<string, string> | null>(null);
  const [tireWearOpen, setTireWearOpen] = useState(false);
  // Local draft заметок механика — синхронизируется с ins.notes когда осмотр
  // прогружается / обновляется. Кнопка «Сохранить» появляется только когда
  // draft отличается от сохранённого (см. notesDirty ниже).
  const [notesDraft, setNotesDraft] = useState<string>("");

  useEffect(() => { loadZoneLabels().then(setZoneLabels); }, []);

  const { data: ins, isLoading, isError } = useQuery({
    queryKey: ["inspection", insId],
    queryFn: () => getInspection(insId),
  });

  useEffect(() => {
    if (ins?.notes !== undefined) setNotesDraft(ins.notes ?? "");
  }, [ins?.notes]);

  const finalize = useMutation({
    mutationFn: () =>
      // При завершении осмотра коммитим текст заметки тем же patch'ем —
      // если механик что-то ввёл и сразу нажал «Завершить», не теряем.
      patchInspection(insId, {
        status: "completed",
        notes: (notesDraft ?? "").trim() || undefined,
      }),
    onSuccess: () => {
      toast.success("Осмотр завершён");
      navigate(`/inspections/${insId}`);
    },
    onError: () => toast.error("Не удалось завершить"),
  });

  const notesMutation = useMutation({
    mutationFn: (next: string) => patchInspection(insId, { notes: next }),
    onSuccess: (updated) => {
      toast.success("Заметка сохранена");
      qc.setQueryData(["inspection", insId], updated);
    },
    onError: () => toast.error("Не удалось сохранить заметку"),
  });

  const removeMarker = useMutation({
    mutationFn: (markerId: number) => deleteMarker(markerId),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ["inspection", insId] });
      toast.success("Метка удалена");
    },
    onError: () => toast.error("Не удалось удалить"),
  });

  if (isLoading) return <div className="p-8 text-muted-foreground">Загружаю…</div>;
  if (isError || !ins)
    return <div className="p-8 text-destructive">Осмотр не найден.</div>;

  // Photos lookup by side+slot for initialPhotoId
  const photosBySide = new Map<string, typeof ins.photos[0]>();
  for (const p of ins.photos) photosBySide.set(`${p.side}-${p.slot_index}`, p);
  // Photos lookup by id — нужен для marker thumb (annotated vs original)
  const photosById = new Map<number, typeof ins.photos[0]>();
  for (const p of ins.photos) photosById.set(p.id, p);

  const editable = ins.status === "in_progress";

  const handleZoneTap = (zoneId: number) => {
    const label = zoneLabels?.[String(zoneId)] ?? `зона ${zoneId}`;
    setFlow({ kind: "confirm", zoneId, zoneLabel: label });
  };

  return (
    <div className="min-h-screen bg-background p-4 space-y-4">
      <button
        onClick={() => navigate(-1)}
        className="text-sm text-muted-foreground hover:text-foreground"
      >
        ← Назад
      </button>

      <div>
        <h1 className="text-xl font-semibold">
          Осмотр #{ins.id}{" "}
          <span className="text-muted-foreground text-base">({ins.type})</span>
        </h1>
        <div className="text-xs text-muted-foreground">
          {new Date(ins.started_at).toLocaleString("ru-RU")}
        </div>
      </div>

      <Card className="p-4">
        <h2 className="text-sm font-semibold text-muted-foreground mb-3">
          Схема — тапните на зону, чтобы добавить метку
        </h2>
        <VendorVehicleScheme
          markers={ins.markers.map((m: MarkerSummary) => ({
            id: m.id,
            side: m.side,
            damage_type: m.damage_type,
            severity: m.severity,
            resolved: m.resolved,
            polygon: m.polygon,
          }))}
          onZoneTap={editable ? handleZoneTap : undefined}
          onTireWearClick={editable ? () => setTireWearOpen(true) : undefined}
          editable={editable}
        />
      </Card>

      {/* Блок «Заметки» поднят сразу под схему — главное текстовое поле для
          планового осмотра, не хочется чтобы механик пролистывал фото+метки
          чтобы добраться до textarea. */}
      <Card className="p-4 space-y-2">
        <h2 className="text-sm font-semibold text-muted-foreground">
          Заметки механика
        </h2>
        {editable ? (
          <>
            <textarea
              value={notesDraft}
              onChange={(e) => setNotesDraft(e.target.value)}
              placeholder="Текст осмотра, замечания, рекомендации…"
              rows={Math.max(3, Math.min(notesDraft.split("\n").length + 1, 12))}
              className="w-full text-sm p-2 rounded border border-input bg-background resize-y focus:outline-none focus:ring-2 focus:ring-ring"
            />
            {(notesDraft ?? "") !== (ins.notes ?? "") && (
              <div className="flex gap-2 justify-end">
                <button
                  type="button"
                  onClick={() => setNotesDraft(ins.notes ?? "")}
                  className="text-xs text-muted-foreground hover:text-foreground px-3 py-1"
                  disabled={notesMutation.isPending}
                >
                  Отменить
                </button>
                <button
                  type="button"
                  onClick={() => notesMutation.mutate(notesDraft)}
                  disabled={notesMutation.isPending}
                  className="text-xs bg-primary text-primary-foreground rounded px-3 py-1 disabled:opacity-60"
                >
                  {notesMutation.isPending ? "Сохраняю…" : "Сохранить"}
                </button>
              </div>
            )}
          </>
        ) : (
          <div className="text-sm whitespace-pre-wrap">{ins.notes || "—"}</div>
        )}
      </Card>

      {/* Multi-step damage flow */}
      {flow.kind === "confirm" && (
        <ZoneConfirmDialog
          open
          zoneLabel={flow.zoneLabel}
          onConfirm={() =>
            setFlow({ kind: "placePoints", zoneId: flow.zoneId, zoneLabel: flow.zoneLabel })
          }
          onCancel={() => setFlow({ kind: "idle" })}
        />
      )}

      {flow.kind === "placePoints" && (
        <ZoneDetailView
          open
          zoneId={flow.zoneId}
          zoneLabel={flow.zoneLabel}
          onConfirm={(points) =>
            setFlow({ kind: "classify", zoneId: flow.zoneId, zoneLabel: flow.zoneLabel, points })
          }
          onCancel={() => setFlow({ kind: "idle" })}
        />
      )}

      {flow.kind === "classify" && (
        <DamageClassifyDialog
          open
          zoneId={flow.zoneId}
          zoneLabel={flow.zoneLabel}
          pointsCount={flow.points.length}
          onCancel={() =>
            setFlow({ kind: "placePoints", zoneId: flow.zoneId, zoneLabel: flow.zoneLabel })
          }
          onSave={({ damageType, severity }) =>
            setFlow({
              kind: "capture",
              zoneId: flow.zoneId,
              zoneLabel: flow.zoneLabel,
              points: flow.points,
              damageType,
              severity,
            })
          }
        />
      )}

      {flow.kind === "capture" && (
        <CapturePhotoStep
          zoneLabel={flow.zoneLabel}
          onCancel={() => setFlow({ kind: "idle" })}
          onPhotoCaptured={(file) =>
            setFlow({
              kind: "annotate",
              zoneId: flow.zoneId,
              zoneLabel: flow.zoneLabel,
              points: flow.points,
              damageType: flow.damageType,
              severity: flow.severity,
              photoFile: file,
            })
          }
        />
      )}

      {flow.kind === "annotate" && (
        <PhotoAnnotateStep
          photoFile={flow.photoFile}
          zoneLabel={flow.zoneLabel}
          onCancel={() =>
            setFlow({
              kind: "capture",
              zoneId: flow.zoneId,
              zoneLabel: flow.zoneLabel,
              points: flow.points,
              damageType: flow.damageType,
              severity: flow.severity,
            })
          }
          onSubmit={async (annotated) => {
            try {
              const damageEnum = damageTypeRuToEnum(flow.damageType);
              if (!damageEnum) {
                toast.error(`Не поддерживается: ${flow.damageType}`);
                setFlow({ kind: "idle" });
                return;
              }
              const result = await uploadPhoto(insId, "free", 0, flow.photoFile);
              if (annotated) {
                try {
                  await uploadPhotoAnnotation(insId, result.id, annotated);
                } catch (err) {
                  // Аннотация — best-effort. Фото оригинал уже сохранилось.
                  console.warn("annotation upload failed (non-fatal)", err);
                }
              }
              await createMarker(insId, {
                side: `zone-${flow.zoneId}`,
                polygon: flow.points,
                damage_type: damageEnum,
                severity: SEVERITY_MAP[flow.severity],
                photo_id: result.id,
              });
              void qc.invalidateQueries({ queryKey: ["inspection", insId] });
              toast.success("Повреждение записано");
            } catch (err) {
              console.error("save failed", err);
              toast.error("Не удалось сохранить");
            } finally {
              setFlow({ kind: "idle" });
            }
          }}
        />
      )}

      <TireWearDialog
        open={tireWearOpen}
        inspectionId={insId}
        onClose={() => setTireWearOpen(false)}
        onCreated={() => {
          setTireWearOpen(false);
          void qc.invalidateQueries({ queryKey: ["inspection", insId] });
          toast.success("Состояние резины записано");
        }}
      />

      <div>
        <h2 className="text-sm font-semibold text-muted-foreground mb-2">Фото</h2>
        <div className="grid grid-cols-2 gap-2">
          {slotsForType(ins.type).map((s) => (
            <PhotoSlot
              key={`${s.side}-0`}
              inspectionId={insId}
              side={s.side}
              slotIndex={0}
              label={s.label}
              initialPhotoId={photosBySide.get(`${s.side}-0`)?.id}
              onUploaded={() =>
                void qc.invalidateQueries({ queryKey: ["inspection", insId] })
              }
            />
          ))}
        </div>
      </div>

      {ins.markers.length > 0 && (
        <div>
          <h2 className="text-sm font-semibold text-muted-foreground mb-2">
            Метки ({ins.markers.length})
          </h2>
          <ul className="space-y-1">
            {ins.markers.map((m: MarkerSummary) => (
              <li key={m.id}>
                <Card className="p-3 text-sm">
                  <div className="flex items-center justify-between">
                    <div>
                      <span className="font-medium capitalize">
                        {humanizeMarkerSide(m.side, zoneLabels)}
                      </span>
                      {" — "}
                      <span>
                        {m.damage_type
                          ? (DAMAGE_TYPE_LABELS[m.damage_type] ?? m.damage_type)
                          : "—"}
                      </span>
                      {m.severity && (
                        <>
                          {" — "}
                          <span className="text-muted-foreground">
                            {SEVERITY_LABELS[m.severity] ?? m.severity}
                          </span>
                        </>
                      )}
                    </div>
                    <div className="flex items-center gap-2">
                      {m.carried_over_from_id && (
                        <span className="text-xs text-muted-foreground">
                          перенесено
                        </span>
                      )}
                      {!m.carried_over_from_id &&
                        m.description?.startsWith("Перенесено из Element Mechanic") && (
                          <span className="text-xs text-muted-foreground">
                            из Element Mechanic
                          </span>
                        )}
                      {editable && (
                        <button
                          onClick={() => {
                            const verb = m.carried_over_from_id
                              ? "Удалить (повреждение устранено в ремонте)?"
                              : "Удалить метку?";
                            if (window.confirm(verb)) {
                              removeMarker.mutate(m.id);
                            }
                          }}
                          disabled={removeMarker.isPending}
                          className="text-xs text-destructive hover:underline px-1"
                          title="Удалить метку"
                        >
                          ✕
                        </button>
                      )}
                    </div>
                  </div>
                  {m.description && (
                    <div className="text-xs text-muted-foreground mt-1">
                      {m.description}
                    </div>
                  )}
                  {m.photo_id ? (
                    <div className="mt-2 max-w-[8rem]">
                      <AuthImg
                        src={
                          photosById.get(m.photo_id)?.annotated_key
                            ? `photos/${m.photo_id}/annotated`
                            : `photos/${m.photo_id}/thumb`
                        }
                        alt="Фото повреждения"
                        className="w-full aspect-[4/3] object-cover rounded bg-muted"
                      />
                    </div>
                  ) : m.tt_image_id ? (
                    <div className="mt-2 max-w-[8rem]">
                      <img
                        src={ttImageUrl(m.tt_image_id)}
                        alt="Фото из Element Mechanic"
                        loading="lazy"
                        className="w-full aspect-[4/3] object-cover rounded bg-muted"
                      />
                    </div>
                  ) : null}
                </Card>
              </li>
            ))}
          </ul>
        </div>
      )}

      {editable && (
        <Button
          className="w-full"
          onClick={() => finalize.mutate()}
          disabled={finalize.isPending}
        >
          {finalize.isPending ? "Завершаем…" : "Завершить осмотр"}
        </Button>
      )}
    </div>
  );
}

function CapturePhotoStep({
  zoneLabel,
  onCancel,
  onPhotoCaptured,
}: {
  zoneLabel: string;
  onCancel: () => void;
  onPhotoCaptured: (file: File) => void;
}) {
  return (
    <div className="fixed inset-0 z-50 bg-background flex flex-col">
      <header className="p-4 border-b">
        <div className="text-xs text-muted-foreground">Фото повреждения</div>
        <h2 className="text-lg font-semibold capitalize">{zoneLabel}</h2>
      </header>
      <main className="flex-1 p-4 flex flex-col justify-center max-w-md w-full mx-auto">
        <CameraCapture
          onCapture={onPhotoCaptured}
          buttonLabel="Сделать фото"
        />
        <Button
          variant="outline"
          onClick={onCancel}
          className="mt-4 w-full"
        >
          Отмена
        </Button>
      </main>
    </div>
  );
}
