"use client";

/**
 * Leave — 在线请假（批次 A）
 *
 * 数据源：useMyLeaveRequests + useCreateLeaveRequest + useCancelLeaveRequest
 * 视图：请假记录列表 + 新建请假表单（react-hook-form + zod 校验）
 */

import { useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import {
  useMyLeaveRequests,
  useCreateLeaveRequest,
  useCancelLeaveRequest,
} from "@/lib/graphql/hooks";
import type { LeaveRequest, LeaveStatus, LeaveType } from "@/lib/graphql/types";

const leaveSchema = z.object({
  leaveType: z.enum(["sick", "personal", "family", "other"]),
  startDate: z.string().min(1, "请选择开始日期"),
  endDate: z.string().min(1, "请选择结束日期"),
  reason: z.string().min(5, "请填写请假原因（至少 5 字）"),
});

type LeaveFormData = z.infer<typeof leaveSchema>;

const LEAVE_TYPE_LABELS: Record<LeaveType, string> = {
  sick: "病假",
  personal: "事假",
  family: "家事假",
  other: "其他",
};

const LEAVE_STATUS_LABELS: Record<LeaveStatus, string> = {
  pending: "待审批",
  approved: "已批准",
  rejected: "已驳回",
  cancelled: "已撤销",
};

const LEAVE_STATUS_BADGE: Record<LeaveStatus, string> = {
  pending: "badge-warning",
  approved: "badge-success",
  rejected: "badge-danger",
  cancelled: "badge-info",
};

export default function LeavePage(): JSX.Element {
  const { data, fetching, error, reexecute } = useMyLeaveRequests();
  const [showForm, setShowForm] = useState(false);

  const requests = data ?? [];

  return (
    <div className="px-6 lg:px-10 py-8 lg:py-10 max-w-5xl mx-auto">
      <header className="mb-6">
        <p className="text-xs uppercase tracking-wider" style={{ color: "var(--color-ink-muted)" }}>
          考勤事务
        </p>
        <h1 className="mt-2 text-3xl lg:text-4xl font-serif" style={{ color: "var(--color-ink)" }}>
          在线请假
        </h1>
        <p className="mt-2 text-sm" style={{ color: "var(--color-ink-muted)" }}>
          提交请假申请，审批通过后自动同步考勤记录。
        </p>
      </header>

      <div className="rule-thin mb-8" />

      <div className="mb-6">
        <button
          type="button"
          onClick={() => setShowForm((v) => !v)}
          className="btn-primary text-sm"
        >
          {showForm ? "取消" : "新建请假申请"}
        </button>
      </div>

      {showForm && (
        <LeaveForm
          onSuccess={() => {
            setShowForm(false);
            reexecute();
          }}
        />
      )}

      {fetching ? (
        <LoadingSkeleton />
      ) : error ? (
        <ErrorState message={error.message} onRetry={() => reexecute()} />
      ) : requests.length === 0 ? (
        <EmptyState />
      ) : (
        <ul className="space-y-4">
          {requests.map((req) => (
            <LeaveCard key={req.id} request={req} onCancelled={() => reexecute()} />
          ))}
        </ul>
      )}
    </div>
  );
}

function LeaveForm({ onSuccess }: { onSuccess: () => void }): JSX.Element {
  const { execute, fetching, errors } = useCreateLeaveRequest();
  const {
    register,
    handleSubmit,
    reset,
    formState: { errors: formErrors },
  } = useForm<LeaveFormData>({
    defaultValues: {
      leaveType: "sick",
      startDate: "",
      endDate: "",
      reason: "",
    },
  });

  const onSubmit = (data: LeaveFormData): void => {
    const result = leaveSchema.safeParse(data);
    if (!result.success) return;
    execute({
      leaveType: result.data.leaveType,
      startDate: result.data.startDate,
      endDate: result.data.endDate,
      reason: result.data.reason,
    });
    reset();
    onSuccess();
  };

  return (
    <form
      onSubmit={handleSubmit(onSubmit)}
      className="card-paper p-6 mb-6 space-y-4"
    >
      <div>
        <label
          className="block text-xs uppercase tracking-wider mb-1"
          style={{ color: "var(--color-ink-muted)" }}
        >
          请假类型
        </label>
        <select
          {...register("leaveType")}
          className="w-full px-3 py-2 rounded-sm text-sm"
          style={{
            background: "var(--color-paper)",
            border: "1px solid var(--color-rule)",
            color: "var(--color-ink)",
          }}
        >
          <option value="sick">病假</option>
          <option value="personal">事假</option>
          <option value="family">家事假</option>
          <option value="other">其他</option>
        </select>
      </div>

      <div className="grid grid-cols-2 gap-4">
        <div>
          <label
            className="block text-xs uppercase tracking-wider mb-1"
            style={{ color: "var(--color-ink-muted)" }}
          >
            开始日期
          </label>
          <input
            type="date"
            {...register("startDate", { required: "请选择开始日期" })}
            className="w-full px-3 py-2 rounded-sm text-sm"
            style={{
              background: "var(--color-paper)",
              border: "1px solid var(--color-rule)",
              color: "var(--color-ink)",
            }}
          />
          {formErrors.startDate && (
            <p className="mt-1 text-xs" style={{ color: "var(--color-danger)" }}>
              {formErrors.startDate.message}
            </p>
          )}
        </div>
        <div>
          <label
            className="block text-xs uppercase tracking-wider mb-1"
            style={{ color: "var(--color-ink-muted)" }}
          >
            结束日期
          </label>
          <input
            type="date"
            {...register("endDate", { required: "请选择结束日期" })}
            className="w-full px-3 py-2 rounded-sm text-sm"
            style={{
              background: "var(--color-paper)",
              border: "1px solid var(--color-rule)",
              color: "var(--color-ink)",
            }}
          />
          {formErrors.endDate && (
            <p className="mt-1 text-xs" style={{ color: "var(--color-danger)" }}>
              {formErrors.endDate.message}
            </p>
          )}
        </div>
      </div>

      <div>
        <label
          className="block text-xs uppercase tracking-wider mb-1"
          style={{ color: "var(--color-ink-muted)" }}
        >
          请假原因
        </label>
        <textarea
          {...register("reason", { required: "请填写请假原因", minLength: 5 })}
          rows={3}
          className="w-full px-3 py-2 rounded-sm text-sm"
          style={{
            background: "var(--color-paper)",
            border: "1px solid var(--color-rule)",
            color: "var(--color-ink)",
          }}
        />
        {formErrors.reason && (
          <p className="mt-1 text-xs" style={{ color: "var(--color-danger)" }}>
            {formErrors.reason.message ?? "请填写请假原因（至少 5 字）"}
          </p>
        )}
      </div>

      {errors.length > 0 && (
        <p className="text-xs" style={{ color: "var(--color-danger)" }}>
          {errors[0]?.message}
        </p>
      )}

      <div className="flex gap-3">
        <button type="submit" disabled={fetching} className="btn-primary text-sm disabled:opacity-50">
          {fetching ? "提交中..." : "提交申请"}
        </button>
      </div>
    </form>
  );
}

function LeaveCard({
  request,
  onCancelled,
}: {
  request: LeaveRequest;
  onCancelled: () => void;
}): JSX.Element {
  const { execute } = useCancelLeaveRequest();

  const handleCancel = (): void => {
    execute({ id: request.id });
    onCancelled();
  };

  return (
    <li>
      <article className="card-paper p-5">
        <div className="flex items-start justify-between gap-4 mb-2">
          <div className="flex items-center gap-2">
            <span className="badge badge-info">
              {LEAVE_TYPE_LABELS[request.leaveType]}
            </span>
            <span className={`badge ${LEAVE_STATUS_BADGE[request.status]}`}>
              {LEAVE_STATUS_LABELS[request.status]}
            </span>
          </div>
          {request.status === "pending" && (
            <button
              type="button"
              onClick={handleCancel}
              className="text-xs"
              style={{ color: "var(--color-ink-muted)" }}
            >
              撤销
            </button>
          )}
        </div>
        <p className="text-sm" style={{ color: "var(--color-ink)" }}>
          {request.startDate} 至 {request.endDate}
        </p>
        <p className="mt-1 text-sm" style={{ color: "var(--color-ink-muted)" }}>
          {request.reason}
        </p>
        {request.reviewComment && (
          <p className="mt-2 text-xs italic" style={{ color: "var(--color-ink-subtle)" }}>
            审批意见（{request.reviewerName}）：{request.reviewComment}
          </p>
        )}
        <p className="mt-2 text-xs" style={{ color: "var(--color-ink-muted)" }}>
          {request.className} · 考勤同步：{request.attendanceSynced ? "已同步" : "未同步"}
        </p>
      </article>
    </li>
  );
}

function LoadingSkeleton(): JSX.Element {
  return (
    <div className="space-y-4" aria-busy="true" aria-live="polite">
      {[0, 1, 2].map((i) => (
        <div
          key={i}
          className="h-28 animate-pulse rounded-sm"
          style={{ background: "var(--color-rule)", opacity: 0.3 }}
        />
      ))}
      <span className="sr-only">正在加载请假记录...</span>
    </div>
  );
}

function ErrorState({ message, onRetry }: { message: string; onRetry: () => void }): JSX.Element {
  return (
    <div role="alert" className="card-paper p-8 text-center" style={{ borderColor: "var(--color-danger)" }}>
      <p className="text-base font-serif" style={{ color: "var(--color-danger)" }}>
        请假记录加载失败
      </p>
      <p className="mt-2 text-sm" style={{ color: "var(--color-ink-muted)" }}>
        {message}
      </p>
      <button type="button" onClick={onRetry} className="mt-4 btn-secondary text-xs">
        重新加载
      </button>
    </div>
  );
}

function EmptyState(): JSX.Element {
  return (
    <div className="card-paper p-8 text-center">
      <p className="text-4xl font-serif" style={{ color: "var(--color-ink-subtle)" }} aria-hidden="true">
        ◇
      </p>
      <p className="mt-4 text-base font-serif" style={{ color: "var(--color-ink)" }}>
        暂无请假记录
      </p>
      <p className="mt-2 text-sm" style={{ color: "var(--color-ink-muted)" }}>
        点击上方"新建请假申请"提交请假。
      </p>
    </div>
  );
}
