"use client";

import { type ReactNode, useState } from "react";
import { DndContext, type DragEndEvent, closestCenter } from "@dnd-kit/core";
import {
  SortableContext,
  arrayMove,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import type { ViewportConfigViewModel } from "@/types/view-models";
import { useViewports, useUpdateViewport } from "@/hooks/use-viewports";
import { useToast } from "@/providers/toast-provider";
import {
  PageHeader,
  PaperCard,
  Button,
  LoadingState,
  ErrorState,
  EmptyState,
  Input,
  Select,
} from "@/components/ui";
import { t } from "@/lib/i18n";

interface SortableViewportItemProps {
  viewport: ViewportConfigViewModel;
  onToggleVisible: (id: string, isVisible: boolean) => void;
  onLabelChange: (id: string, label: string) => void;
  onPermissionChange: (id: string, perm: string | null) => void;
}

function SortableViewportItem({
  viewport,
  onToggleVisible,
  onLabelChange,
  onPermissionChange,
}: SortableViewportItemProps): ReactNode {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: viewport.id });

  const style: React.CSSProperties = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
    padding: "12px 16px",
    borderBottom: "1px solid var(--color-rule)",
    display: "grid",
    gridTemplateColumns: "24px 120px 1fr 180px 80px 80px",
    gap: 12,
    alignItems: "center",
    background: "var(--bg-paper)",
    fontSize: 13,
  };

  return (
    <div ref={setNodeRef} style={style}>
      <button
        {...attributes}
        {...listeners}
        aria-label="拖拽排序"
        style={{
          cursor: "grab",
          background: "none",
          border: "none",
          color: "var(--color-ink-muted)",
        }}
      >
        ⋮⋮
      </button>
      <span style={{ fontFamily: "var(--font-mono)", fontSize: 12 }}>
        {viewport.key}
      </span>
      <Input
        type="text"
        value={viewport.label}
        onChange={(e) => onLabelChange(viewport.id, e.target.value)}
        style={{ fontSize: 13 }}
      />
      <Input
        type="text"
        value={viewport.requiredPermission ?? ""}
        onChange={(e) =>
          onPermissionChange(viewport.id, e.target.value || null)
        }
        placeholder="无需权限"
        style={{ fontSize: 12, fontFamily: "var(--font-mono)" }}
      />
      <span style={{ fontSize: 11, color: "var(--color-ink-muted)" }}>
        {viewport.scope}
      </span>
      <span style={{ display: "flex", alignItems: "center", gap: 4 }}>
        <input
          type="checkbox"
          checked={viewport.isVisible}
          onChange={(e) => onToggleVisible(viewport.id, e.target.checked)}
          aria-label="是否可见"
        />
      </span>
    </div>
  );
}

export default function ViewportsPage(): ReactNode {
  const { data: viewports, loading, error } = useViewports();
  const { show } = useToast();
  const [updateViewport] = useUpdateViewport();
  const [localViewports, setLocalViewports] = useState<
    ViewportConfigViewModel[] | null
  >(null);
  const [scopeFilter, setScopeFilter] = useState<string>("all");

  // 同步远端数据
  if (viewports.length > 0 && localViewports === null) {
    setLocalViewports(viewports);
  }

  const filteredViewports = (localViewports ?? viewports).filter(
    (v) => scopeFilter === "all" || v.scope === scopeFilter,
  );

  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;
    if (!over || active.id === over.id) return;
    if (!localViewports) return;
    const oldIndex = localViewports.findIndex((v) => v.id === active.id);
    const newIndex = localViewports.findIndex((v) => v.id === over.id);
    if (oldIndex < 0 || newIndex < 0) return;
    const reordered = arrayMove(localViewports, oldIndex, newIndex).map(
      (v, i) => ({ ...v, sortOrder: i + 1 }),
    );
    setLocalViewports(reordered);
  };

  const handleToggleVisible = async (id: string, isVisible: boolean) => {
    try {
      await updateViewport(id, { isVisible });
      show("success", "已更新");
      setLocalViewports(
        (prev) =>
          prev?.map((v) => (v.id === id ? { ...v, isVisible } : v)) ?? null,
      );
    } catch (err) {
      show(
        "error",
        "更新失败",
        err instanceof Error ? err.message : String(err),
      );
    }
  };

  const handleLabelChange = async (id: string, label: string) => {
    setLocalViewports(
      (prev) => prev?.map((v) => (v.id === id ? { ...v, label } : v)) ?? null,
    );
  };

  const handlePermissionChange = async (id: string, perm: string | null) => {
    setLocalViewports(
      (prev) =>
        prev?.map((v) =>
          v.id === id ? { ...v, requiredPermission: perm } : v,
        ) ?? null,
    );
  };

  const handleSaveOrder = async () => {
    if (!localViewports) return;
    try {
      for (const vp of localViewports) {
        await updateViewport(vp.id, {
          sortOrder: vp.sortOrder,
          label: vp.label,
          requiredPermission: vp.requiredPermission,
          isVisible: vp.isVisible,
        });
      }
      show("success", "全部已保存");
    } catch (err) {
      show(
        "error",
        "保存失败",
        err instanceof Error ? err.message : String(err),
      );
    }
  };

  return (
    <div style={{ padding: 32, maxWidth: 1200, margin: "0 auto" }}>
      <PageHeader
        title={t("admin.viewports.title")}
        description="配置各端视口的路由、权限与排序"
        actions={
          <>
            <Select
              value={scopeFilter}
              onChange={(e) => setScopeFilter(e.target.value)}
            >
              <option value="all">{t("admin.common.all")}</option>
              <option value="teacher">教师端</option>
              <option value="student">学生端</option>
              <option value="parent">家长端</option>
              <option value="admin">管理端</option>
            </Select>
            <Button variant="primary" onClick={handleSaveOrder}>
              {t("admin.common.save")}
            </Button>
          </>
        }
      />

      <PaperCard className="p-4">
        {loading && <LoadingState />}
        {error && <ErrorState message={error.message} />}
        {!loading && !error && (
          <>
            {filteredViewports.length === 0 ? (
              <EmptyState message={t("admin.common.empty")} />
            ) : (
              <>
                <div
                  style={{
                    padding: "8px 16px",
                    borderBottom: "2px solid var(--color-rule)",
                    display: "grid",
                    gridTemplateColumns: "24px 120px 1fr 180px 80px 80px",
                    gap: 12,
                    fontSize: 11,
                    color: "var(--color-ink-muted)",
                    textTransform: "uppercase",
                    letterSpacing: "0.05em",
                  }}
                >
                  <span></span>
                  <span>{t("admin.viewports.key")}</span>
                  <span>{t("admin.viewports.label")}</span>
                  <span>{t("admin.viewports.requiredPermission")}</span>
                  <span>{t("admin.viewports.scope")}</span>
                  <span>{t("admin.viewports.visible")}</span>
                </div>
                <DndContext
                  collisionDetection={closestCenter}
                  onDragEnd={handleDragEnd}
                >
                  <SortableContext
                    items={filteredViewports.map((v) => v.id)}
                    strategy={verticalListSortingStrategy}
                  >
                    {filteredViewports.map((vp) => (
                      <SortableViewportItem
                        key={vp.id}
                        viewport={vp}
                        onToggleVisible={handleToggleVisible}
                        onLabelChange={handleLabelChange}
                        onPermissionChange={handlePermissionChange}
                      />
                    ))}
                  </SortableContext>
                </DndContext>
                <p
                  style={{
                    fontSize: 11,
                    color: "var(--color-ink-muted)",
                    marginTop: 12,
                    padding: "0 16px",
                  }}
                >
                  {t("admin.viewports.dragHint")}
                </p>
              </>
            )}
          </>
        )}
      </PaperCard>
    </div>
  );
}
