import { formatDate, formatDateTime, formatDuration, formatTime, kindColor, kindLabel } from "./editorPresentation";
import { statusStyle } from "../tgu-planning/tguStatus";
import type { RvaZone } from "../../api/ballisticsApi";
import type { SurveyRoute, SurveyRouteAnchor } from "../../api/missionPlanningApi";
import type { Tgu2DMapSelection } from "../tgu-map-2d/model/mapSelectionTypes";
import type { RequestMapItem } from "../../model/requestTypes";
import type {
  EditorGroundStation,
  EditorMode,
  EditorTarget,
  EditorVisibilityWindow,
  EditorWork,
  EditorWorkPatch
} from "./model/editorTypes";

export type DownlinkSelection = {
  station: EditorGroundStation;
  pass: EditorVisibilityWindow;
};

export type DownlinkStationOption = {
  station: EditorGroundStation;
  passes: EditorVisibilityWindow[];
};

type WorkInspectorProps = {
  work: EditorWork;
  modes: EditorMode[];
  stations: EditorGroundStation[];
  conflicts: string[];
  onUpdate: (workId: string, patch: EditorWorkPatch) => void;
  onDelete: (workId: string) => void;
  onDuplicate: (workId: string) => void;
  onClose: () => void;
};

type ShootPanelProps = {
  target?: EditorTarget;
  passes: EditorVisibilityWindow[];
  loading?: boolean;
  error?: string;
  selectedPass?: EditorVisibilityWindow;
  modeId?: string;
  modes: EditorMode[];
  routeAnchor: SurveyRouteAnchor;
  routeLoading?: boolean;
  routeError?: string;
  route?: SurveyRoute;
  onAnchorChange: (anchor: SurveyRouteAnchor) => void;
  onSelectPass: (pass?: EditorVisibilityWindow) => void;
  onModeChange: (modeId: string) => void;
  onAdd: () => void;
  onClose: () => void;
  onClearTarget: () => void;
};

type DownlinkPanelProps = {
  stationOptions: DownlinkStationOption[];
  selected?: DownlinkSelection;
  onSelect: (selection?: DownlinkSelection) => void;
  onAdd: () => void;
  onClose: () => void;
};

/** Маршрут съёмки — кандидат на сброс в выбранной зоне (заканчивается до начала зоны). */
export type DropCandidateSurvey = {
  id: number;
  label: string;
  startMs: number;
  endMs: number;
};

type DropPanelProps = {
  zones: RvaZone[];
  loading?: boolean;
  error?: string;
  selectedZone?: RvaZone;
  onSelectZone: (zone?: RvaZone) => void;
  /** Название станции по её номеру (из каталога станций). */
  stationName: (stationId: number) => string;
  /** Время начала зоны в мс (UTC) — для подписи. */
  zoneStartMs: (zone: RvaZone) => number;
  zoneStopMs: (zone: RvaZone) => number;
  /** Съёмки-кандидаты для выбранной зоны (end < начало зоны). */
  candidates: DropCandidateSurvey[];
  selectedSurveyIds: Set<number>;
  onToggleSurvey: (id: number) => void;
  saving?: boolean;
  saveError?: string;
  onAdd: () => void;
  onClose: () => void;
};

export function WorkInspector({
  work,
  modes,
  stations,
  conflicts,
  onUpdate,
  onDelete,
  onDuplicate,
  onClose
}: WorkInspectorProps) {
  const color = kindColor(work.kind);

  return (
    <div className="tgu-editor-panel">
      <PanelHead title={kindLabel(work.kind)} onClose={onClose} />
      <div className="tgu-editor-panel__id">{work.id}</div>

      {conflicts.length > 0 && (
        <div className="tgu-alert tgu-alert--warning">
          {conflicts.map((conflict) => (
            <div key={conflict}>{conflict}</div>
          ))}
        </div>
      )}

      <section className="tgu-editor-panel__section">
        <div className="tgu-editor-eyebrow">Время</div>
        <TimeStepper label="начало" value={work.startMs} max={work.endMs - 60_000} onChange={(value) => onUpdate(work.id, { startMs: value })} />
        <TimeStepper label="конец" value={work.endMs} min={work.startMs + 60_000} onChange={(value) => onUpdate(work.id, { endMs: value })} />
        <div className="tgu-editor-panel__hint">длительность: {formatDuration(work.endMs - work.startMs)}</div>
      </section>

      {work.kind === "shoot" && (
        <section className="tgu-editor-panel__section">
          <div className="tgu-editor-eyebrow">Режим аппаратуры</div>
          <div className="tgu-editor-chip-row">
            {modes.map((mode) => (
              <button
                className={work.modeId === mode.id ? "is-selected" : ""}
                key={mode.id}
                type="button"
                onClick={() => onUpdate(work.id, { modeId: mode.id, label: mode.label })}
              >
                {mode.label}
              </button>
            ))}
          </div>
          {work.targetName && <div className="tgu-editor-panel__hint">цель: {work.targetName}</div>}
        </section>
      )}

      {work.kind === "downlink" && (
        <section className="tgu-editor-panel__section">
          <div className="tgu-editor-eyebrow">Станция приёма</div>
          <select value={work.stationId ?? ""} onChange={(event) => onUpdate(work.id, { stationId: event.target.value })}>
            {stations.map((station) => (
              <option key={station.id} value={station.id}>
                {station.name}
              </option>
            ))}
          </select>
        </section>
      )}

      <div className="tgu-editor-panel__actions">
        <button className="tgu-button" type="button" onClick={() => onDuplicate(work.id)}>
          Дублировать
        </button>
        <button className="tgu-button tgu-button--reject" type="button" onClick={() => onDelete(work.id)}>
          Удалить
        </button>
      </div>

      <span className="tgu-editor-panel__color" style={{ background: color }} aria-hidden="true" />
    </div>
  );
}

export function ShootPanel({
  target,
  passes,
  loading,
  error,
  selectedPass,
  modeId,
  modes,
  routeAnchor,
  routeLoading,
  routeError,
  route,
  onAnchorChange,
  onSelectPass,
  onModeChange,
  onAdd,
  onClose,
  onClearTarget
}: ShootPanelProps) {
  return (
    <div className="tgu-editor-panel">
      <PanelHead title="Новая съёмка" onClose={onClose} />

      <section className="tgu-editor-panel__section">
        <div className="tgu-editor-panel__section-head">
          <div className="tgu-editor-eyebrow">1 · цель съёмки</div>
          {target && (
            <button className="tgu-link-button" type="button" onClick={onClearTarget}>
              сбросить
            </button>
          )}
        </div>
        {!target ? (
          <div className="tgu-editor-panel__placeholder">Кликните точку на карте слева, чтобы выбрать цель съёмки.</div>
        ) : (
          <div className="tgu-editor-target">
            <i />
            <span>{target.name}</span>
            <small>
              {target.lat.toFixed(2)}, {target.lon.toFixed(2)}
            </small>
          </div>
        )}
      </section>

      {target && (
        <section className="tgu-editor-panel__section">
          <div className="tgu-editor-eyebrow">2 · окно видимости</div>
          {loading ? (
            <div className="tgu-editor-panel__hint">Запрос параметров видимости…</div>
          ) : error ? (
            <div className="tgu-alert tgu-alert--danger tgu-alert--compact">{error}</div>
          ) : passes.length === 0 ? (
            <div className="tgu-editor-panel__hint">В окне планирования проходов над целью нет.</div>
          ) : (
            <div className="tgu-editor-pass-list">
              {passes.map((pass) => {
                const selected = selectedPass?.startMs === pass.startMs && selectedPass.endMs === pass.endMs;
                return (
                  <button
                    className={selected ? "is-selected" : ""}
                    key={`${pass.startMs}-${pass.endMs}`}
                    type="button"
                    onClick={() => onSelectPass(pass)}
                  >
                    <span>
                      {formatDate(pass.startMs)} {formatTime(pass.startMs)}
                      {pass.revolution != null && ` · виток ${pass.revolution}`}
                    </span>
                    <small>{formatVisibilityParams(pass)}</small>
                  </button>
                );
              })}
            </div>
          )}
        </section>
      )}

      {target && selectedPass && (
        <section className="tgu-editor-panel__section">
          <div className="tgu-editor-eyebrow">3 · режим съёмки</div>
          <div className="tgu-editor-chip-row">
            {modes.map((mode) => (
              <button className={modeId === mode.id ? "is-selected" : ""} key={mode.id} type="button" onClick={() => onModeChange(mode.id)}>
                {mode.label}
              </button>
            ))}
          </div>
        </section>
      )}

      {target && selectedPass && (
        <section className="tgu-editor-panel__section">
          <div className="tgu-editor-eyebrow">4 · маршрут съёмки</div>
          <div className="tgu-editor-chip-row">
            <button
              className={routeAnchor === "CENTERED" ? "is-selected" : ""}
              type="button"
              onClick={() => onAnchorChange("CENTERED")}
            >
              вокруг момента
            </button>
            <button
              className={routeAnchor === "FORWARD" ? "is-selected" : ""}
              type="button"
              onClick={() => onAnchorChange("FORWARD")}
            >
              от момента вперёд
            </button>
          </div>
          {routeLoading ? (
            <div className="tgu-editor-panel__hint">Построение маршрута…</div>
          ) : routeError ? (
            <div className="tgu-alert tgu-alert--danger tgu-alert--compact">{routeError}</div>
          ) : route ? (
            <div className="tgu-editor-panel__hint">
              Маршрут построен · виток {route.revolution} · крен {route.roll.toFixed(1)}° · захват {route.captureAngle.toFixed(1)}°
              <br />
              центр {route.lat.toFixed(2)}, {route.longitude.toFixed(2)} · контур показан на карте
            </div>
          ) : null}
        </section>
      )}

      <button className="tgu-button tgu-button--primary" type="button" onClick={onAdd} disabled={!target || !selectedPass || !modeId}>
        + Добавить съёмку в план
      </button>
    </div>
  );
}

export function DownlinkPanel({ stationOptions, selected, onSelect, onAdd, onClose }: DownlinkPanelProps) {
  return (
    <div className="tgu-editor-panel">
      <PanelHead title="Новый сброс на НКПОР" onClose={onClose} />
      <div className="tgu-editor-panel__hint">Выберите станцию и сеанс связи для добавления сброса в черновик.</div>

      <div className="tgu-editor-station-list">
        {stationOptions.map((option) => (
          <div className="tgu-editor-station" key={option.station.id}>
            <div className="tgu-editor-station__head">
              <span>{option.station.name}</span>
              <small>{option.passes.length} сеанс.</small>
            </div>
            {option.passes.length === 0 ? (
              <div className="tgu-editor-panel__hint">нет сеансов в текущем окне</div>
            ) : (
              option.passes.slice(0, 5).map((pass) => {
                const isSelected = selected?.station.id === option.station.id && selected.pass.startMs === pass.startMs;
                return (
                  <button
                    className={isSelected ? "is-selected" : ""}
                    key={`${option.station.id}-${pass.startMs}`}
                    type="button"
                    onClick={() => onSelect({ station: option.station, pass })}
                  >
                    <span>{formatDateTime(pass.startMs)}-{formatTime(pass.endMs)}</span>
                    <small>{formatDuration(pass.endMs - pass.startMs)}</small>
                  </button>
                );
              })
            )}
          </div>
        ))}
      </div>

      <button className="tgu-button tgu-button--primary" type="button" onClick={onAdd} disabled={!selected}>
        + Добавить сброс в план
      </button>
    </div>
  );
}

export function DropPanel({
  zones,
  loading,
  error,
  selectedZone,
  onSelectZone,
  stationName,
  zoneStartMs,
  zoneStopMs,
  candidates,
  selectedSurveyIds,
  onToggleSurvey,
  saving,
  saveError,
  onAdd,
  onClose
}: DropPanelProps) {
  const canAdd = !!selectedZone && selectedSurveyIds.size > 0 && !saving;

  return (
    <div className="tgu-editor-panel">
      <PanelHead title="Новый сброс по ЗРВ" onClose={onClose} />
      <div className="tgu-editor-panel__hint">
        Выберите зону радиовидимости станции, затем маршруты съёмки, которые успевают завершиться до начала зоны.
      </div>

      {loading && <div className="tgu-editor-panel__hint">Загрузка зон радиовидимости…</div>}
      {error && <div className="tgu-alert tgu-alert--danger">{error}</div>}
      {!loading && !error && zones.length === 0 && (
        <div className="tgu-editor-panel__hint">Нет зон радиовидимости в текущем окне.</div>
      )}

      {zones.length > 0 && (
        <div className="tgu-editor-station-list">
          {zones.map((zone) => {
            const startMs = zoneStartMs(zone);
            const stopMs = zoneStopMs(zone);
            const isSelected =
              !!selectedZone &&
              selectedZone.stationId === zone.stationId &&
              selectedZone.revolution === zone.revolution &&
              selectedZone.onStart.time === zone.onStart.time;
            return (
              <button
                className={isSelected ? "is-selected" : ""}
                key={`${zone.stationId}-${zone.revolution}-${zone.onStart.time}`}
                type="button"
                onClick={() => onSelectZone(isSelected ? undefined : zone)}
              >
                <span>{stationName(zone.stationId)} · виток {zone.revolution}</span>
                <small>
                  {formatDateTime(startMs)}–{formatTime(stopMs)} · {formatDuration(stopMs - startMs)}
                </small>
              </button>
            );
          })}
        </div>
      )}

      {selectedZone && (
        <section className="tgu-editor-panel__section">
          <div className="tgu-editor-eyebrow">Съёмки для сброса</div>
          {candidates.length === 0 ? (
            <div className="tgu-editor-panel__hint">Нет съёмок, завершающихся до начала выбранной зоны.</div>
          ) : (
            <div className="tgu-editor-station-list">
              {candidates.map((survey) => {
                const checked = selectedSurveyIds.has(survey.id);
                return (
                  <button
                    className={checked ? "is-selected" : ""}
                    key={survey.id}
                    type="button"
                    onClick={() => onToggleSurvey(survey.id)}
                  >
                    <span>{checked ? "☑" : "☐"} {survey.label}</span>
                    <small>
                      {formatDateTime(survey.startMs)}–{formatTime(survey.endMs)}
                    </small>
                  </button>
                );
              })}
            </div>
          )}
        </section>
      )}

      {saveError && <div className="tgu-alert tgu-alert--danger">{saveError}</div>}

      <button className="tgu-button tgu-button--primary" type="button" onClick={onAdd} disabled={!canAdd}>
        {saving ? "Сохранение…" : "+ Добавить сброс в план"}
      </button>
    </div>
  );
}

type MapInfoPanelProps = {
  selection: Tgu2DMapSelection;
  requestItems: RequestMapItem[];
  onClose: () => void;
};

export function MapInfoPanel({ selection, requestItems, onClose }: MapInfoPanelProps) {
  const title = mapInfoTitle(selection);

  const requestItem =
    selection.type === "polygon" && selection.layer === "requests" && selection.requestId
      ? requestItems.find((r) => r.id === selection.requestId)
      : undefined;

  return (
    <div className="tgu-editor-panel">
      <PanelHead title={title} onClose={onClose} />

      {selection.type === "marker" && selection.layer === "stations" && (
        <section className="tgu-editor-panel__section">
          <div className="tgu-editor-eyebrow">{selection.name}</div>
          <dl className="tgu-map-request-details__grid">
            <dt>Номер</dt>
            <dd className="mono">{selection.stationNumber ?? "—"}</dd>
            <dt>Широта</dt>
            <dd className="mono">{selection.lat != null ? `${selection.lat.toFixed(4)}°` : "—"}</dd>
            <dt>Долгота</dt>
            <dd className="mono">{selection.lon != null ? `${selection.lon.toFixed(4)}°` : "—"}</dd>
            <dt>Высота, м</dt>
            <dd className="mono">{selection.altitude != null ? selection.altitude.toFixed(1) : "—"}</dd>
            <dt>Угол места мин, °</dt>
            <dd className="mono">{selection.elevationMin != null ? selection.elevationMin.toFixed(1) : "—"}</dd>
            <dt>Угол места макс, °</dt>
            <dd className="mono">{selection.elevationMax != null ? selection.elevationMax.toFixed(1) : "—"}</dd>
          </dl>
        </section>
      )}

      {selection.type === "polygon" && selection.layer === "requests" && (
        requestItem ? (
          <section className="tgu-editor-panel__section">
            <dl className="tgu-map-request-details__grid">
              <dt>ID</dt>
              <dd className="mono">{requestItem.id}</dd>
              <dt>Название</dt>
              <dd>{requestItem.name || "—"}</dd>
              <dt>Статус</dt>
              <dd>{requestItem.status}</dd>
              <dt>Тип съёмки</dt>
              <dd>{surveyTypeLabel(requestItem.surveyType)}</dd>
              <dt>Начало</dt>
              <dd className="mono">{formatIso(requestItem.beginDateTime)}</dd>
              <dt>Конец</dt>
              <dd className="mono">{formatIso(requestItem.endDateTime)}</dd>
              <dt>Важность</dt>
              <dd className="mono">{requestItem.importance}</dd>
              <dt>Покрытие</dt>
              <dd className="mono">{requestItem.coveragePercent != null ? `${requestItem.coveragePercent.toFixed(1)} %` : "—"}</dd>
              <dt>КПП</dt>
              <dd className="mono">{requestItem.kpp?.join(", ") || "—"}</dd>
              <dt>Приоритет передачи</dt>
              <dd>{requestItem.highPriorityTransmit ? "Да" : "Нет"}</dd>
            </dl>
          </section>
        ) : (
          <div className="tgu-editor-panel__hint">{selection.name || selection.id}</div>
        )
      )}

      {selection.type === "polygon" && selection.layer === "planWorks" && (
        <section className="tgu-editor-panel__section">
          <div className="tgu-editor-eyebrow">{selection.name}</div>
          {selection.status && (
            <span className="tgu-map-status-pill">
              <i style={{ backgroundColor: statusStyle(selection.status).color }} />
              {statusStyle(selection.status).label}
            </span>
          )}
        </section>
      )}
    </div>
  );
}

function mapInfoTitle(selection: Tgu2DMapSelection): string {
  if (selection.type === "marker") {
    return selection.layer === "stations" ? "Станция" : "Маркер КА";
  }
  switch (selection.layer) {
    case "requests": return "Заявка на съёмку";
    case "planWorks": return "Работа плана";
    case "swath": return "Полоса обзора";
    case "tracks": return "Трасса КА";
    default: return "Объект карты";
  }
}

function formatVisibilityParams(pass: EditorVisibilityWindow): string {
  const parts: string[] = [formatDuration(pass.endMs - pass.startMs)];
  if (pass.rollDeg != null) parts.push(`крен ${pass.rollDeg.toFixed(1)}°`);
  if (pass.sunAngleDeg != null) parts.push(`☉ ${pass.sunAngleDeg.toFixed(1)}°`);
  if (pass.range != null) {
    const km = pass.range > 100000 ? pass.range / 1000 : pass.range;
    parts.push(`${km.toFixed(0)} км`);
  }
  return parts.join(" · ");
}

function surveyTypeLabel(surveyType: string): string {
  switch (surveyType) {
    case "OPTICS": return "Оптическая";
    case "RSA": return "Радиолокационная (РСА)";
    case "COMBINED": return "Комбинированная";
    default: return surveyType;
  }
}

function formatIso(iso: string): string {
  return new Date(iso).toLocaleString("ru-RU");
}

function PanelHead({ title, onClose }: { title: string; onClose: () => void }) {
  return (
    <div className="tgu-editor-panel__head">
      <h2>{title}</h2>
      <button className="tgu-icon-button" type="button" onClick={onClose} title="Закрыть">
        ×
      </button>
    </div>
  );
}

function TimeStepper({
  label,
  value,
  min,
  max,
  onChange
}: {
  label: string;
  value: number;
  min?: number;
  max?: number;
  onChange: (value: number) => void;
}) {
  const change = (deltaMs: number) => {
    const next = Math.max(min ?? Number.NEGATIVE_INFINITY, Math.min(max ?? Number.POSITIVE_INFINITY, value + deltaMs));
    onChange(next);
  };

  return (
    <label className="tgu-editor-time-stepper">
      <span>{label}</span>
      <div>
        <button type="button" onClick={() => change(-3_600_000)}>−ч</button>
        <button type="button" onClick={() => change(-5 * 60_000)}>−5м</button>
        <output>{formatDateTime(value)}</output>
        <button type="button" onClick={() => change(5 * 60_000)}>+5м</button>
        <button type="button" onClick={() => change(3_600_000)}>+ч</button>
      </div>
    </label>
  );
}
