"use client";

import Link from "next/link";
import { useCallback, useMemo, type ReactNode } from "react";
import { GitBranch } from "lucide-react";
import { BrapiEntityPage, type BrapiFormField } from "@/components/brapi/BrapiEntityPage";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  createLinkageGroupRow,
  createLinkageGroupRowFromPayload,
  deleteLinkageGroupRow,
  fetchLinkageGroupRows,
  loadLinkageGroupPageData,
  normalizeLinkageGroupFormData,
  updateLinkageGroupRow,
} from "../api";
import { NONE_SELECT_VALUE, type LinkageGroupQuery, type SelectOption } from "../types";

const optionOrNone = (label: string, options: SelectOption[]) => [
  { value: NONE_SELECT_VALUE, label },
  ...options,
];

interface LinkageGroupEntityPageProps {
  /** 详情页固定所属图谱；入口 Tab 不传则跨图谱列表维护 */
  mapDbId?: string;
  mapOptions?: SelectOption[];
  linkageGroupQuery?: LinkageGroupQuery;
  onChanged?: () => void;
  defaultFormValues?: Record<string, unknown>;
  renderQueryForm?: () => ReactNode;
}

export function LinkageGroupEntityPage({
  mapDbId,
  mapOptions = [],
  linkageGroupQuery,
  onChanged,
  defaultFormValues,
  renderQueryForm,
}: LinkageGroupEntityPageProps) {
  const scopedToMap = Boolean(mapDbId);
  const includeMapInForm = !scopedToMap;

  const loadRows = useCallback(async () => {
    if (scopedToMap && mapDbId) {
      const rows = await fetchLinkageGroupRows(mapDbId);
      return rows as unknown as Record<string, unknown>[];
    }
    const { rows } = await loadLinkageGroupPageData({ query: linkageGroupQuery });
    return rows as unknown as Record<string, unknown>[];
  }, [scopedToMap, mapDbId, linkageGroupQuery]);

  const resolveMapDbId = useCallback((payload: Record<string, unknown>, row?: Record<string, unknown>) => {
    if (mapDbId) return mapDbId;
    const fromPayload = String(payload.map_db_id ?? "").trim();
    if (fromPayload && fromPayload !== NONE_SELECT_VALUE) return fromPayload;
    return String(row?.map_db_id ?? row?.mapDbId ?? "").trim();
  }, [mapDbId]);

  const fields = useMemo<BrapiFormField[]>(() => {
    const base: BrapiFormField[] = [];
    if (includeMapInForm) {
      base.push({
        key: "map_db_id",
        label: "所属图谱",
        type: "select",
        required: true,
        options: optionOrNone("请选择图谱", mapOptions),
      });
    }
    base.push(
      { key: "linkage_group_name", label: "连锁群名称", type: "text", required: true, placeholder: "如 Chr01" },
      { key: "max_position", label: "最大位置", type: "number", placeholder: "可选，非负整数" },
    );
    return base;
  }, [includeMapInForm, mapOptions]);

  const columns = useMemo(() => {
    const cols = [
      {
        key: "linkage_group_name",
        label: "名称",
        render: (value: unknown, row: Record<string, unknown>) => {
          const name = String(value ?? "—");
          const targetMapId = resolveMapDbId({}, row);
          if (!targetMapId) return name;
          return (
            <Link
              href={`/genotyping/genome-map/maps/${encodeURIComponent(targetMapId)}/linkage-groups/${encodeURIComponent(String(row.id ?? ""))}`}
              className="font-medium text-teal-600 hover:underline dark:text-teal-400"
            >
              {name}
            </Link>
          );
        },
      },
    ];
    if (!scopedToMap) {
      cols.push({
        key: "map_name",
        label: "所属图谱",
        render: (value: unknown, row: Record<string, unknown>) => {
          const targetMapId = resolveMapDbId({}, row);
          const label = String(value ?? row.map_name ?? "—");
          if (!targetMapId) return label;
          return (
            <Link
              href={`/genotyping/genome-map/maps/${encodeURIComponent(targetMapId)}`}
              className="text-teal-600 hover:underline dark:text-teal-400"
            >
              {label}
            </Link>
          );
        },
      });
    }
    cols.push(
      { key: "max_position", label: "最大位置", render: (value: unknown) => String(value ?? "—") },
      {
        key: "marker_count",
        label: "Marker 数",
        render: (value: unknown) => <Badge variant="outline">{Number(value ?? 0)}</Badge>,
      },
    );
    return cols;
  }, [scopedToMap, resolveMapDbId]);

  const wrapMutation = useCallback(<T, >(action: () => Promise<T>) => async () => {
    const result = await action();
    onChanged?.();
    return result;
  }, [onChanged]);

  return (
    <BrapiEntityPage
      useEnhancedDialog
      icon={GitBranch}
      iconBg="bg-gradient-to-br from-teal-500 to-emerald-600"
      title={scopedToMap ? "连锁群 Linkage Group" : "Linkage Group 连锁群"}
      description={
        scopedToMap
          ? "该图谱下的连锁群；删除前请确认无 Marker Position 引用。"
          : "跨图谱维护连锁群；新增时需选择所属 GenomeMap，也可在图谱详情中维护。"
      }
      addLabel="新增连锁群"
      defaultFormValues={defaultFormValues}
      columns={columns}
      fields={fields}
      data={[]}
      stats={[{
        label: scopedToMap ? `/maps/${mapDbId}/linkagegroups` : "聚合 /maps/*/linkagegroups",
        value: "BrAPI",
        className: "bg-emerald-50 text-emerald-700 dark:bg-emerald-400/10 dark:text-emerald-200",
      }]}
      loadData={loadRows}
      fetchRecord={async (id) => {
        if (scopedToMap && mapDbId) {
          const rows = await fetchLinkageGroupRows(mapDbId);
          const row = rows.find((item) => item.id === id);
          if (!row) throw new Error("连锁群不存在");
          return normalizeLinkageGroupFormData(row);
        }
        const { rows } = await loadLinkageGroupPageData({ force: true });
        const row = rows.find((item) => item.id === id);
        if (!row) throw new Error("连锁群不存在");
        return normalizeLinkageGroupFormData(row, true);
      }}
      createRecord={(payload) => {
        if (scopedToMap && mapDbId) {
          return wrapMutation(() => createLinkageGroupRow(mapDbId, payload))() as Promise<Record<string, unknown>>;
        }
        return wrapMutation(() => createLinkageGroupRowFromPayload(payload))() as Promise<Record<string, unknown>>;
      }}
      updateRecord={async (id, payload) => {
        const targetMapId = resolveMapDbId(payload);
        if (!targetMapId) throw new Error("无法确定所属图谱");
        return wrapMutation(() => updateLinkageGroupRow(targetMapId, id, payload))() as Promise<Record<string, unknown>>;
      }}
      deleteRecord={async (id) => {
        let targetMapId = mapDbId;
        if (!targetMapId) {
          const { rows } = await loadLinkageGroupPageData({ force: true });
          const row = rows.find((item) => item.id === id);
          targetMapId = row?.map_db_id || undefined;
        }
        if (!targetMapId) throw new Error("无法确定所属图谱");
        await wrapMutation(() => deleteLinkageGroupRow(targetMapId, id))();
      }}
      renderQueryForm={renderQueryForm}
      renderFormExtra={({ editingRow }) => (
        <>
          <div className="md:col-span-2 space-y-1.5">
            <Label className="text-sm text-slate-700 dark:text-slate-200">LinkageGroup ID</Label>
            {editingRow ? (
              <Input
                value={String(editingRow.id ?? "")}
                readOnly
                disabled
                className="bg-slate-50 dark:bg-slate-900"
              />
            ) : (
              <p className="rounded-md border border-dashed border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">
                保存后由系统自动生成
              </p>
            )}
            <p className="text-xs text-slate-500">数据库主键，新增与修改时均不可编辑。</p>
          </div>
          <div className="col-span-2 rounded-lg border border-emerald-100 bg-emerald-50/60 p-3 text-xs text-emerald-900 dark:border-emerald-900/40 dark:bg-emerald-950/30 dark:text-emerald-100">
            <p className="font-medium">校验说明</p>
            <p className="mt-1 text-emerald-800/80 dark:text-emerald-200/80">
              同一图谱下连锁群名称不可重复；删除前需无 Marker Position 引用。
            </p>
          </div>
        </>
      )}
    />
  );
}
