"use client";

import { useState, useEffect, useRef } from "react";
import { useFocusTrap } from "~/hooks/useFocusTrap.js";
import { OrderType, AllocationType, ProjectStatus } from "@capakraken/shared";
import type { Project } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { DateInput } from "~/components/ui/DateInput.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";

const ORDER_TYPE_OPTIONS = [
  { value: "BD", label: "BD" },
  { value: "CHARGEABLE", label: "Chargeable" },
  { value: "INTERNAL", label: "Internal" },
  { value: "OVERHEAD", label: "Overhead" },
] as const;

const ALLOCATION_TYPE_OPTIONS = [
  { value: "INT", label: "INT" },
  { value: "EXT", label: "EXT" },
] as const;

const STATUS_OPTIONS = [
  { value: "DRAFT", label: "Draft" },
  { value: "ACTIVE", label: "Active" },
  { value: "ON_HOLD", label: "On Hold" },
  { value: "COMPLETED", label: "Completed" },
  { value: "CANCELLED", label: "Cancelled" },
] as const;

function formatDateForInput(date: Date | string): string {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
}

interface FormState {
  shortCode: string;
  name: string;
  orderType: string;
  allocationType: string;
  winProbability: string;
  budgetEur: string;
  startDate: string;
  endDate: string;
  status: string;
  responsiblePerson: string;
  color: string;
  utilizationCategoryId: string;
  clientId: string;
  shoringThreshold: string;
}

function getDefaultForm(): FormState {
  const today = formatDateForInput(new Date());
  return {
    shortCode: "",
    name: "",
    orderType: "CHARGEABLE",
    allocationType: "INT",
    winProbability: "100",
    budgetEur: "",
    startDate: today,
    endDate: today,
    status: "DRAFT",
    responsiblePerson: "",
    color: "",
    utilizationCategoryId: "",
    clientId: "",
    shoringThreshold: "55",
  };
}

function projectToForm(project: Project): FormState {
  return {
    shortCode: project.shortCode,
    name: project.name,
    orderType: project.orderType,
    allocationType: project.allocationType,
    winProbability: String(project.winProbability),
    budgetEur: String(Math.round(project.budgetCents) / 100),
    startDate: formatDateForInput(project.startDate),
    endDate: formatDateForInput(project.endDate),
    status: project.status,
    responsiblePerson: project.responsiblePerson ?? "",
    color: (project as unknown as { color?: string | null }).color ?? "",
    utilizationCategoryId: (project as unknown as { utilizationCategoryId?: string | null }).utilizationCategoryId ?? "",
    clientId: (project as unknown as { clientId?: string | null }).clientId ?? "",
    shoringThreshold: String((project as unknown as { shoringThreshold?: number | null }).shoringThreshold ?? 55),
  };
}

interface ProjectModalProps {
  project?: Project | null;
  onClose: () => void;
  onSuccess?: (name: string) => void;
}

export function ProjectModal({ project, onClose, onSuccess }: ProjectModalProps) {
  const isEdit = !!project;
  const utils = trpc.useUtils();

  const [form, setForm] = useState<FormState>(() =>
    project ? projectToForm(project) : getDefaultForm(),
  );
  const [errors, setErrors] = useState<Partial<Record<keyof FormState, string>>>({});
  const [serverError, setServerError] = useState<string | null>(null);

  const panelRef = useRef<HTMLDivElement>(null);
  useFocusTrap(panelRef, true);

  const { data: utilizationCategories } = trpc.utilizationCategory.list.useQuery(undefined, { staleTime: 60_000 });
  const { data: clientList } = trpc.clientEntity.list.useQuery(undefined, { staleTime: 60_000 });

  // @ts-ignore TS2589: tRPC infers union type too deeply for CreateProjectSchema with .refine()
  const createMutation = trpc.project.create.useMutation({
    onSuccess: async () => {
      await utils.project.listWithCosts.invalidate();
      onSuccess?.(form.name.trim());
      onClose();
    },
    onError: (err) => {
      setServerError(err.message);
    },
  });

  const updateMutation = trpc.project.update.useMutation({
    onSuccess: async () => {
      await utils.project.listWithCosts.invalidate();
      onSuccess?.(form.name.trim());
      onClose();
    },
    onError: (err) => {
      setServerError(err.message);
    },
  });

  const isLoading = createMutation.isPending || updateMutation.isPending;

  // Close on Escape key
  useEffect(() => {
    function handleKeyDown(e: KeyboardEvent) {
      if (e.key === "Escape") onClose();
    }
    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, [onClose]);

  function setField<K extends keyof FormState>(key: K, value: FormState[K]) {
    setForm((prev) => ({ ...prev, [key]: value }));
    setErrors((prev) => ({ ...prev, [key]: undefined }));
    setServerError(null);
  }

  function validate(): boolean {
    const newErrors: Partial<Record<keyof FormState, string>> = {};

    if (!isEdit && !form.shortCode.trim()) {
      newErrors.shortCode = "Short code is required.";
    } else if (!isEdit && !/^[A-Z0-9_-]+$/.test(form.shortCode.trim())) {
      newErrors.shortCode = "Must be uppercase alphanumeric (A-Z, 0-9, _, -).";
    }

    if (!form.name.trim()) {
      newErrors.name = "Name is required.";
    }

    const winProb = Number(form.winProbability);
    if (isNaN(winProb) || winProb < 0 || winProb > 100) {
      newErrors.winProbability = "Must be between 0 and 100.";
    }

    const budget = parseFloat(form.budgetEur);
    if (isNaN(budget) || budget < 0) {
      newErrors.budgetEur = "Must be a positive number.";
    }

    if (!form.startDate) {
      newErrors.startDate = "Start date is required.";
    }

    if (!form.endDate) {
      newErrors.endDate = "End date is required.";
    } else if (form.startDate && form.endDate < form.startDate) {
      newErrors.endDate = "End date must be on or after start date.";
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!validate()) return;

    const budgetCents = Math.round(parseFloat(form.budgetEur) * 100);
    const winProbability = Number(form.winProbability);

    if (isEdit && project) {
      updateMutation.mutate({
        id: project.id,
        data: {
          name: form.name.trim(),
          orderType: form.orderType as unknown as OrderType,
          allocationType: form.allocationType as unknown as AllocationType,
          winProbability,
          budgetCents,
          startDate: new Date(form.startDate),
          endDate: new Date(form.endDate),
          status: form.status as unknown as ProjectStatus,
          responsiblePerson: form.responsiblePerson.trim(),
          ...(form.color ? { color: form.color } : {}),
          ...(form.utilizationCategoryId ? { utilizationCategoryId: form.utilizationCategoryId } : {}),
          ...(form.clientId ? { clientId: form.clientId } : {}),
          shoringThreshold: Number(form.shoringThreshold),
        },
      });
    } else {
      createMutation.mutate({
        shortCode: form.shortCode.trim(),
        name: form.name.trim(),
        orderType: form.orderType as unknown as OrderType,
        allocationType: form.allocationType as unknown as AllocationType,
        winProbability,
        budgetCents,
        startDate: new Date(form.startDate),
        endDate: new Date(form.endDate),
        status: form.status as unknown as ProjectStatus,
        staffingReqs: [],
        dynamicFields: {},
        responsiblePerson: form.responsiblePerson.trim(),
        ...(form.color ? { color: form.color } : {}),
        ...(form.utilizationCategoryId ? { utilizationCategoryId: form.utilizationCategoryId } : {}),
        ...(form.clientId ? { clientId: form.clientId } : {}),
        shoringThreshold: Number(form.shoringThreshold),
      });
    }
  }

  const inputClass =
    "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 text-sm dark:bg-gray-900 dark:text-gray-100";
  const inputErrorClass =
    "w-full px-3 py-2 border border-red-400 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-400 text-sm dark:bg-gray-900 dark:text-gray-100";
  const labelClass = "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1";

  return (
    <div
      className="fixed inset-0 bg-black/50 z-50 flex items-start justify-center overflow-y-auto py-8"
      onClick={(e) => {
        if (e.target === e.currentTarget) onClose();
      }}
    >
      <div
        ref={panelRef}
        className="bg-white dark:bg-gray-800 rounded-xl shadow-2xl w-full max-w-xl mx-4"
        onKeyDown={(e) => { if (e.key === "Escape") onClose(); }}
      >
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700">
          <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">
            {isEdit ? "Edit Project" : "New Project"}
          </h2>
          <button
            type="button"
            onClick={onClose}
            className="text-gray-400 hover:text-gray-600 transition-colors"
            aria-label="Close"
          >
            <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* Form */}
        <form onSubmit={handleSubmit} noValidate>
          <div className="px-6 py-5 space-y-6">
            {serverError && (
              <div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg px-4 py-3 text-sm text-red-700 dark:text-red-400">
                {serverError}
              </div>
            )}

            {/* Section 1: Identity */}
            <fieldset>
              <legend className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-3">
                Identity
              </legend>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className={labelClass} htmlFor="shortCode">
                    Chargecode <span className="text-red-500">*</span>
                    <InfoTooltip content="Unique project identifier for time tracking and cost attribution. Cannot be changed after creation." />
                  </label>
                  <input
                    id="shortCode"
                    type="text"
                    value={form.shortCode}
                    onChange={(e) => setField("shortCode", e.target.value.toUpperCase())}
                    disabled={isEdit}
                    placeholder="PRJ-001"
                    className={
                      isEdit
                        ? `${inputClass} bg-gray-50 dark:bg-gray-700 text-gray-500 dark:text-gray-400 cursor-not-allowed`
                        : errors.shortCode
                          ? inputErrorClass
                          : inputClass
                    }
                  />
                  {errors.shortCode && (
                    <p className="mt-1 text-xs text-red-600 dark:text-red-400">{errors.shortCode}</p>
                  )}
                </div>
                <div>
                  <label className={labelClass} htmlFor="name">
                    Name <span className="text-red-500">*</span>
                    <InfoTooltip content="Display name shown on the timeline and in reports." />
                  </label>
                  <input
                    id="name"
                    type="text"
                    value={form.name}
                    onChange={(e) => setField("name", e.target.value)}
                    placeholder="Project name"
                    className={errors.name ? inputErrorClass : inputClass}
                  />
                  {errors.name && (
                    <p className="mt-1 text-xs text-red-600 dark:text-red-400">{errors.name}</p>
                  )}
                </div>
              </div>
            </fieldset>

            {/* Section 2: Classification */}
            <fieldset>
              <legend className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-3">
                Classification
              </legend>
              <div className="grid grid-cols-3 gap-4">
                <div>
                  <label className={labelClass} htmlFor="orderType">
                    Order Type
                    <InfoTooltip content="BD = Business Development (pre-sales), CHARGEABLE = billable client work, INTERNAL = internal project, OVERHEAD = non-project overhead." />
                  </label>
                  <select
                    id="orderType"
                    value={form.orderType}
                    onChange={(e) => setField("orderType", e.target.value)}
                    className={inputClass}
                  >
                    {ORDER_TYPE_OPTIONS.map((opt) => (
                      <option key={opt.value} value={opt.value}>
                        {opt.label}
                      </option>
                    ))}
                  </select>
                </div>
                <div>
                  <label className={labelClass} htmlFor="allocationType">
                    Allocation
                    <InfoTooltip content="INT = staffed with internal resources, EXT = staffed with external contractors or freelancers." />
                  </label>
                  <select
                    id="allocationType"
                    value={form.allocationType}
                    onChange={(e) => setField("allocationType", e.target.value)}
                    className={inputClass}
                  >
                    {ALLOCATION_TYPE_OPTIONS.map((opt) => (
                      <option key={opt.value} value={opt.value}>
                        {opt.label}
                      </option>
                    ))}
                  </select>
                </div>
                <div>
                  <label className={labelClass} htmlFor="winProbability">
                    Win Probability %
                    <InfoTooltip content="Likelihood of winning this project (0-100%). Affects the weighted pipeline value: budget x probability." />
                  </label>
                  <input
                    id="winProbability"
                    type="number"
                    min={0}
                    max={100}
                    value={form.winProbability}
                    onChange={(e) => setField("winProbability", e.target.value)}
                    className={errors.winProbability ? inputErrorClass : inputClass}
                  />
                  {errors.winProbability && (
                    <p className="mt-1 text-xs text-red-600 dark:text-red-400">{errors.winProbability}</p>
                  )}
                </div>
              </div>
            </fieldset>

            {/* Section: Categorization */}
            <fieldset>
              <legend className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-3">
                Categorization
              </legend>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className={labelClass} htmlFor="utilizationCategoryId">
                    Utilization Category
                    <InfoTooltip content="Groups projects for chargeability and utilization reporting. Determines how hours count toward resource utilization." />
                  </label>
                  <select
                    id="utilizationCategoryId"
                    value={form.utilizationCategoryId}
                    onChange={(e) => setField("utilizationCategoryId", e.target.value)}
                    className={inputClass}
                  >
                    <option value="">— Not specified —</option>
                    {(utilizationCategories ?? []).map((cat) => (
                      <option key={cat.id} value={cat.id}>
                        {(cat as unknown as { code: string }).code} — {(cat as unknown as { name: string }).name}
                      </option>
                    ))}
                  </select>
                </div>
                <div>
                  <label className={labelClass} htmlFor="clientId">
                    Client
                    <InfoTooltip content="The client or customer this project is for. Used for filtering and reporting." />
                  </label>
                  <select
                    id="clientId"
                    value={form.clientId}
                    onChange={(e) => setField("clientId", e.target.value)}
                    className={inputClass}
                  >
                    <option value="">— Not specified —</option>
                    {(clientList ?? []).map((c) => (
                      <option key={c.id} value={c.id}>
                        {(c as unknown as { name: string }).name}
                        {(c as unknown as { code: string | null }).code ? ` [${(c as unknown as { code: string }).code}]` : ""}
                      </option>
                    ))}
                  </select>
                </div>
              </div>
            </fieldset>

            {/* Section 3: Timeline & Budget */}
            <fieldset>
              <legend className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-3">
                Timeline &amp; Budget
              </legend>
              <div className="grid grid-cols-4 gap-4">
                <div>
                  <label className={labelClass} htmlFor="startDate">
                    Start Date
                    <InfoTooltip content="First day of the project period. Assignments begin from this date." />
                  </label>
                  <DateInput
                    id="startDate"
                    value={form.startDate}
                    onChange={(v) => setField("startDate", v)}
                    className={errors.startDate ? inputErrorClass : inputClass}
                  />
                  {errors.startDate && (
                    <p className="mt-1 text-xs text-red-600 dark:text-red-400">{errors.startDate}</p>
                  )}
                </div>
                <div>
                  <label className={labelClass} htmlFor="endDate">
                    End Date
                    <InfoTooltip content="Last day of the project period. Must be on or after the start date." />
                  </label>
                  <DateInput
                    id="endDate"
                    value={form.endDate}
                    min={form.startDate}
                    onChange={(v) => setField("endDate", v)}
                    className={errors.endDate ? inputErrorClass : inputClass}
                  />
                  {errors.endDate && (
                    <p className="mt-1 text-xs text-red-600 dark:text-red-400">{errors.endDate}</p>
                  )}
                </div>
                <div>
                  <label className={labelClass} htmlFor="budgetEur">
                    Budget (€)
                    <InfoTooltip content="Total project budget in EUR. Tracked against the sum of assignment costs (hours x daily rate)." />
                  </label>
                  <input
                    id="budgetEur"
                    type="number"
                    min={0}
                    step="0.01"
                    value={form.budgetEur}
                    onChange={(e) => setField("budgetEur", e.target.value)}
                    placeholder="0.00"
                    className={errors.budgetEur ? inputErrorClass : inputClass}
                  />
                  {errors.budgetEur && (
                    <p className="mt-1 text-xs text-red-600 dark:text-red-400">{errors.budgetEur}</p>
                  )}
                </div>
                <div>
                  <label className={labelClass} htmlFor="shoringThreshold">
                    Min Offshore %
                    <InfoTooltip content="Minimum offshore staffing target (0-100). Green when met, red when below. Higher offshore = more cost-efficient. Default: 55%." />
                  </label>
                  <input
                    id="shoringThreshold"
                    type="number"
                    min={0}
                    max={100}
                    value={form.shoringThreshold}
                    onChange={(e) => setField("shoringThreshold", e.target.value)}
                    placeholder="55"
                    className={inputClass}
                  />
                </div>
              </div>
            </fieldset>

            {/* Section 4: Status */}
            <fieldset>
              <legend className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-3">
                Status
              </legend>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className={labelClass} htmlFor="status">
                    Status
                    <InfoTooltip content="DRAFT = not visible on timeline, ACTIVE = in progress, ON_HOLD = paused, COMPLETED = finished, CANCELLED = abandoned." />
                  </label>
                  <select
                    id="status"
                    value={form.status}
                    onChange={(e) => setField("status", e.target.value)}
                    className={inputClass}
                  >
                    {STATUS_OPTIONS.map((opt) => (
                      <option key={opt.value} value={opt.value}>
                        {opt.label}
                      </option>
                    ))}
                  </select>
                </div>
                <div>
                  <label className={labelClass} htmlFor="responsiblePerson">
                    Responsible Person <span className="text-red-500">*</span>
                    <InfoTooltip content="Project lead or account manager responsible for this project. Required." />
                  </label>
                  <input
                    id="responsiblePerson"
                    type="text"
                    value={form.responsiblePerson}
                    onChange={(e) => setField("responsiblePerson", e.target.value)}
                    placeholder="Name or EID"
                    required
                    className={inputClass}
                  />
                </div>
                <div>
                  <label className={labelClass} htmlFor="projectColor">
                    Timeline Color
                    <InfoTooltip content="Custom color for this project's bars on the timeline view. Leave empty for the default color." />
                  </label>
                  <div className="flex items-center gap-2">
                    <input
                      id="projectColor"
                      type="color"
                      value={form.color || "#3b82f6"}
                      onChange={(e) => setField("color", e.target.value)}
                      className="w-10 h-10 rounded-lg border border-gray-300 dark:border-gray-600 cursor-pointer p-0.5"
                    />
                    <span className="text-xs text-gray-400 dark:text-gray-500">
                      {form.color || "Default"}
                    </span>
                    {form.color && (
                      <button
                        type="button"
                        onClick={() => setField("color", "")}
                        className="text-xs text-gray-400 hover:text-red-500"
                      >
                        Clear
                      </button>
                    )}
                  </div>
                </div>
              </div>
            </fieldset>
          </div>

          {/* Footer */}
          <div className="flex items-center justify-end gap-3 px-6 py-4 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 rounded-b-xl">
            <button
              type="button"
              onClick={onClose}
              disabled={isLoading}
              className="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 transition-colors"
            >
              Cancel
            </button>
            <button
              type="submit"
              disabled={isLoading}
              className="px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 text-sm font-medium disabled:opacity-50 transition-colors"
            >
              {isLoading ? (isEdit ? "Saving…" : "Creating…") : isEdit ? "Save Changes" : "Create Project"}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}
