"use client";

import { useMemo, useState } from "react";
import { clsx } from "clsx";
import { trpc } from "~/lib/trpc/client.js";

interface WeeklyPhasingViewProps {
  estimateId: string;
  canEdit: boolean;
}

type ViewMode = "by_line" | "by_chapter";
type PhasingPattern = "even" | "front_loaded" | "back_loaded";

function getDefaultDateRange(): { start: string; end: string } {
  const now = new Date();
  const start = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-01`;
  const endDate = new Date(now.getFullYear(), now.getMonth() + 6, 0);
  const end = `${endDate.getFullYear()}-${String(endDate.getMonth() + 1).padStart(2, "0")}-${String(endDate.getDate()).padStart(2, "0")}`;
  return { start, end };
}

function heatColor(hours: number, maxHours: number): string {
  if (hours === 0 || maxHours === 0) return "";
  const ratio = Math.min(hours / maxHours, 1);
  if (ratio < 0.25) return "bg-blue-50 dark:bg-blue-900/20";
  if (ratio < 0.5) return "bg-blue-100 dark:bg-blue-900/30";
  if (ratio < 0.75) return "bg-blue-200 dark:bg-blue-900/40";
  return "bg-blue-300 dark:bg-blue-900/50";
}

export function WeeklyPhasingView({ estimateId, canEdit }: WeeklyPhasingViewProps) {
  const defaults = getDefaultDateRange();
  const [startDate, setStartDate] = useState(defaults.start);
  const [endDate, setEndDate] = useState(defaults.end);
  const [pattern, setPattern] = useState<PhasingPattern>("even");
  const [viewMode, setViewMode] = useState<ViewMode>("by_line");

  const utils = trpc.useUtils();

  const phasingQuery = trpc.estimate.getWeeklyPhasing.useQuery(
    { estimateId },
    { staleTime: 30_000 },
  );

  const generateMutation = trpc.estimate.generateWeeklyPhasing.useMutation({
    onSuccess: () => {
      void utils.estimate.getWeeklyPhasing.invalidate({ estimateId });
      void utils.estimate.getById.invalidate({ id: estimateId });
    },
  });

  const data = phasingQuery.data;

  // Compute max hours for heat-map coloring
  const maxHours = useMemo(() => {
    if (!data?.hasPhasing) return 0;
    let max = 0;
    for (const line of data.lines) {
      for (const h of Object.values(line.weeklyHours)) {
        if (h > max) max = h;
      }
    }
    return max;
  }, [data]);

  // Compute column totals
  const columnTotals = useMemo(() => {
    if (!data?.hasPhasing) return {};
    const totals: Record<string, number> = {};
    for (const line of data.lines) {
      for (const [weekKey, hours] of Object.entries(line.weeklyHours)) {
        totals[weekKey] = Math.round(((totals[weekKey] ?? 0) + hours) * 100) / 100;
      }
    }
    return totals;
  }, [data]);

  // Compute chapter column totals
  const chapterColumnTotals = useMemo(() => {
    if (!data?.hasPhasing) return {};
    const totals: Record<string, number> = {};
    for (const chapterHours of Object.values(data.chapterAggregation)) {
      for (const [weekKey, hours] of Object.entries(chapterHours)) {
        totals[weekKey] = Math.round(((totals[weekKey] ?? 0) + hours) * 100) / 100;
      }
    }
    return totals;
  }, [data]);

  // Compute max hours for chapter view
  const maxChapterHours = useMemo(() => {
    if (!data?.hasPhasing) return 0;
    let max = 0;
    for (const chapterHours of Object.values(data.chapterAggregation)) {
      for (const h of Object.values(chapterHours)) {
        if (h > max) max = h;
      }
    }
    return max;
  }, [data]);

  const handleGenerate = () => {
    generateMutation.mutate({
      estimateId,
      startDate,
      endDate,
      pattern,
    });
  };

  // Use config dates from existing phasing if available
  const effectiveStart = data?.hasPhasing ? data.config.startDate : startDate;
  const effectiveEnd = data?.hasPhasing ? data.config.endDate : endDate;

  return (
    <div className="space-y-6">
      {/* Header / Controls */}
      <div className="rounded-3xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-6">
        <h3 className="mb-4 text-lg font-semibold text-gray-900 dark:text-gray-100">
          Weekly Phasing (4Dispo)
        </h3>

        {canEdit && (
          <div className="flex flex-wrap items-end gap-4">
            <div>
              <label className="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                Start Date
              </label>
              <input
                type="date"
                value={data?.hasPhasing ? effectiveStart : startDate}
                onChange={(e) => setStartDate(e.target.value)}
                className="rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm"
              />
            </div>
            <div>
              <label className="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                End Date
              </label>
              <input
                type="date"
                value={data?.hasPhasing ? effectiveEnd : endDate}
                onChange={(e) => setEndDate(e.target.value)}
                className="rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm"
              />
            </div>
            <div>
              <label className="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                Pattern
              </label>
              <select
                value={pattern}
                onChange={(e) => setPattern(e.target.value as PhasingPattern)}
                className="rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm"
              >
                <option value="even">Even Distribution</option>
                <option value="front_loaded">Front Loaded (60/40)</option>
                <option value="back_loaded">Back Loaded (40/60)</option>
              </select>
            </div>
            <button
              type="button"
              onClick={handleGenerate}
              disabled={generateMutation.isPending}
              className={clsx(
                "rounded-lg px-4 py-2 text-sm font-medium text-white",
                generateMutation.isPending
                  ? "cursor-not-allowed bg-gray-400"
                  : "bg-sky-600 hover:bg-sky-700",
              )}
            >
              {generateMutation.isPending ? "Generating..." : "Generate Phasing"}
            </button>
          </div>
        )}

        {generateMutation.isError && (
          <p className="mt-2 text-sm text-red-600">
            {generateMutation.error.message}
          </p>
        )}

        {generateMutation.isSuccess && (
          <p className="mt-2 text-sm text-emerald-600">
            Phasing generated for {generateMutation.data.linesUpdated} demand
            lines.
          </p>
        )}
      </div>

      {/* View toggle */}
      {data?.hasPhasing && (
        <div className="flex items-center gap-2">
          <button
            type="button"
            onClick={() => setViewMode("by_line")}
            className={clsx(
              "rounded-lg px-3 py-1.5 text-sm font-medium",
              viewMode === "by_line"
                ? "bg-sky-100 dark:bg-sky-900/40 text-sky-700 dark:text-sky-300"
                : "bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600",
            )}
          >
            By Line
          </button>
          <button
            type="button"
            onClick={() => setViewMode("by_chapter")}
            className={clsx(
              "rounded-lg px-3 py-1.5 text-sm font-medium",
              viewMode === "by_chapter"
                ? "bg-sky-100 dark:bg-sky-900/40 text-sky-700 dark:text-sky-300"
                : "bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600",
            )}
          >
            By Chapter
          </button>
        </div>
      )}

      {/* Phasing Grid */}
      {phasingQuery.isLoading && (
        <div className="rounded-3xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-8 text-center text-gray-500 dark:text-gray-400">
          Loading phasing data...
        </div>
      )}

      {data && !data.hasPhasing && (
        <div className="rounded-3xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-8 text-center text-gray-500 dark:text-gray-400">
          No weekly phasing generated yet. Use the controls above to generate a
          phasing distribution.
        </div>
      )}

      {data?.hasPhasing && viewMode === "by_line" && (
        <div className="rounded-3xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 overflow-hidden">
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900">
                  <th className="sticky left-0 z-10 bg-gray-50 dark:bg-gray-900 px-4 py-3 text-left font-medium text-gray-700 dark:text-gray-300 min-w-[200px]">
                    Demand Line
                  </th>
                  {data.weeks.map((week) => {
                    const key = `${week.year}-W${String(week.weekNumber).padStart(2, "0")}`;
                    return (
                      <th
                        key={key}
                        className="px-3 py-3 text-right font-medium text-gray-600 dark:text-gray-400 min-w-[80px] whitespace-nowrap"
                      >
                        {week.label}
                      </th>
                    );
                  })}
                  <th className="sticky right-0 z-10 bg-gray-50 dark:bg-gray-900 px-4 py-3 text-right font-semibold text-gray-700 dark:text-gray-300 min-w-[90px]">
                    Total
                  </th>
                </tr>
              </thead>
              <tbody>
                {data.lines.map((line) => {
                  const lineTotal = Object.values(line.weeklyHours).reduce(
                    (sum, h) => sum + h,
                    0,
                  );
                  return (
                    <tr
                      key={line.id}
                      className="border-b border-gray-100 dark:border-gray-700/50 hover:bg-gray-50/50 dark:hover:bg-gray-700/30"
                    >
                      <td className="sticky left-0 z-10 bg-white dark:bg-gray-800 px-4 py-2 font-medium text-gray-900 dark:text-gray-100">
                        <div className="truncate max-w-[200px]" title={line.name}>
                          {line.name}
                        </div>
                        {line.chapter && (
                          <div className="text-xs text-gray-500 dark:text-gray-400">
                            {line.chapter}
                          </div>
                        )}
                      </td>
                      {data.weeks.map((week) => {
                        const key = `${week.year}-W${String(week.weekNumber).padStart(2, "0")}`;
                        const hours = line.weeklyHours[key] ?? 0;
                        return (
                          <td
                            key={key}
                            className={clsx(
                              "px-3 py-2 text-right tabular-nums text-gray-700 dark:text-gray-200",
                              heatColor(hours, maxHours),
                            )}
                          >
                            {hours > 0 ? hours.toFixed(1) : "-"}
                          </td>
                        );
                      })}
                      <td className="sticky right-0 z-10 bg-white dark:bg-gray-800 px-4 py-2 text-right font-semibold tabular-nums text-gray-900 dark:text-gray-100">
                        {lineTotal.toFixed(1)}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
              <tfoot>
                <tr className="border-t-2 border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-900 font-semibold">
                  <td className="sticky left-0 z-10 bg-gray-50 dark:bg-gray-900 px-4 py-3 text-gray-700 dark:text-gray-300">
                    Total
                  </td>
                  {data.weeks.map((week) => {
                    const key = `${week.year}-W${String(week.weekNumber).padStart(2, "0")}`;
                    const total = columnTotals[key] ?? 0;
                    return (
                      <td
                        key={key}
                        className="px-3 py-3 text-right tabular-nums text-gray-900 dark:text-gray-100"
                      >
                        {total > 0 ? total.toFixed(1) : "-"}
                      </td>
                    );
                  })}
                  <td className="sticky right-0 z-10 bg-gray-50 dark:bg-gray-900 px-4 py-3 text-right tabular-nums text-gray-900 dark:text-gray-100">
                    {Object.values(columnTotals)
                      .reduce((sum, h) => sum + h, 0)
                      .toFixed(1)}
                  </td>
                </tr>
              </tfoot>
            </table>
          </div>
        </div>
      )}

      {data?.hasPhasing && viewMode === "by_chapter" && (
        <div className="rounded-3xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 overflow-hidden">
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900">
                  <th className="sticky left-0 z-10 bg-gray-50 dark:bg-gray-900 px-4 py-3 text-left font-medium text-gray-700 dark:text-gray-300 min-w-[200px]">
                    Chapter
                  </th>
                  {data.weeks.map((week) => {
                    const key = `${week.year}-W${String(week.weekNumber).padStart(2, "0")}`;
                    return (
                      <th
                        key={key}
                        className="px-3 py-3 text-right font-medium text-gray-600 dark:text-gray-400 min-w-[80px] whitespace-nowrap"
                      >
                        {week.label}
                      </th>
                    );
                  })}
                  <th className="sticky right-0 z-10 bg-gray-50 dark:bg-gray-900 px-4 py-3 text-right font-semibold text-gray-700 dark:text-gray-300 min-w-[90px]">
                    Total
                  </th>
                </tr>
              </thead>
              <tbody>
                {Object.entries(data.chapterAggregation)
                  .sort(([a], [b]) => a.localeCompare(b))
                  .map(([chapter, weeklyHours]) => {
                    const chapterTotal = Object.values(weeklyHours).reduce(
                      (sum, h) => sum + h,
                      0,
                    );
                    return (
                      <tr
                        key={chapter}
                        className="border-b border-gray-100 dark:border-gray-700/50 hover:bg-gray-50/50 dark:hover:bg-gray-700/30"
                      >
                        <td className="sticky left-0 z-10 bg-white dark:bg-gray-800 px-4 py-2 font-medium text-gray-900 dark:text-gray-100">
                          {chapter}
                        </td>
                        {data.weeks.map((week) => {
                          const key = `${week.year}-W${String(week.weekNumber).padStart(2, "0")}`;
                          const hours = weeklyHours[key] ?? 0;
                          return (
                            <td
                              key={key}
                              className={clsx(
                                "px-3 py-2 text-right tabular-nums text-gray-700 dark:text-gray-200",
                                heatColor(hours, maxChapterHours),
                              )}
                            >
                              {hours > 0 ? hours.toFixed(1) : "-"}
                            </td>
                          );
                        })}
                        <td className="sticky right-0 z-10 bg-white dark:bg-gray-800 px-4 py-2 text-right font-semibold tabular-nums text-gray-900 dark:text-gray-100">
                          {chapterTotal.toFixed(1)}
                        </td>
                      </tr>
                    );
                  })}
              </tbody>
              <tfoot>
                <tr className="border-t-2 border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-900 font-semibold">
                  <td className="sticky left-0 z-10 bg-gray-50 dark:bg-gray-900 px-4 py-3 text-gray-700 dark:text-gray-300">
                    Total
                  </td>
                  {data.weeks.map((week) => {
                    const key = `${week.year}-W${String(week.weekNumber).padStart(2, "0")}`;
                    const total = chapterColumnTotals[key] ?? 0;
                    return (
                      <td
                        key={key}
                        className="px-3 py-3 text-right tabular-nums text-gray-900 dark:text-gray-100"
                      >
                        {total > 0 ? total.toFixed(1) : "-"}
                      </td>
                    );
                  })}
                  <td className="sticky right-0 z-10 bg-gray-50 dark:bg-gray-900 px-4 py-3 text-right tabular-nums text-gray-900 dark:text-gray-100">
                    {Object.values(chapterColumnTotals)
                      .reduce((sum, h) => sum + h, 0)
                      .toFixed(1)}
                  </td>
                </tr>
              </tfoot>
            </table>
          </div>
        </div>
      )}

      {/* Info about current phasing config */}
      {data?.hasPhasing && data.config && (
        <div className="rounded-3xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-4">
          <p className="text-sm text-gray-600 dark:text-gray-400">
            <span className="font-medium">Current phasing:</span>{" "}
            {data.config.pattern.replace("_", " ")} distribution from{" "}
            {data.config.startDate} to {data.config.endDate} across{" "}
            {data.weeks.length} weeks, {data.lines.length} demand lines.
          </p>
        </div>
      )}
    </div>
  );
}
