"use client";

import { useEffect, useState } from "react";
import Link from "next/link";
import dynamic from "next/dynamic";
import { EstimateExportFormat } from "@capakraken/shared";
import { clsx } from "clsx";
import { useSession } from "next-auth/react";
import type {
  EstimateWorkspaceView,
  WorkspaceTab,
} from "~/components/estimates/EstimateWorkspace.types.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { usePermissions } from "~/hooks/usePermissions.js";
import { formatDateLong } from "~/lib/format.js";
import { trpc } from "~/lib/trpc/client.js";

const TabSkeleton = () => (
  <div className="p-6 space-y-4">
    <div className="h-8 w-48 shimmer-skeleton rounded" />
    <div className="h-64 shimmer-skeleton rounded-xl" />
  </div>
);

const EstimateWorkspaceDraftEditor = dynamic(
  () => import("~/components/estimates/EstimateWorkspaceDraftEditor.js").then((mod) => ({ default: mod.EstimateWorkspaceDraftEditor })),
  { loading: TabSkeleton },
);

const WeeklyPhasingView = dynamic(
  () => import("~/components/estimates/WeeklyPhasingView.js").then((mod) => ({ default: mod.WeeklyPhasingView })),
  { loading: TabSkeleton },
);

const OverviewTab = dynamic(
  () => import("~/components/estimates/tabs/OverviewTab.js").then((mod) => ({ default: mod.OverviewTab })),
  { loading: TabSkeleton },
);

const AssumptionsTab = dynamic(
  () => import("~/components/estimates/tabs/AssumptionsTab.js").then((mod) => ({ default: mod.AssumptionsTab })),
  { loading: TabSkeleton },
);

const ScopeTab = dynamic(
  () => import("~/components/estimates/tabs/ScopeTab.js").then((mod) => ({ default: mod.ScopeTab })),
  { loading: TabSkeleton },
);

const StaffingTab = dynamic(
  () => import("~/components/estimates/tabs/StaffingTab.js").then((mod) => ({ default: mod.StaffingTab })),
  { loading: TabSkeleton },
);

const FinancialsTab = dynamic(
  () => import("~/components/estimates/tabs/FinancialsTab.js").then((mod) => ({ default: mod.FinancialsTab })),
  { loading: TabSkeleton },
);

const VersionsTab = dynamic(
  () => import("~/components/estimates/tabs/VersionsTab.js").then((mod) => ({ default: mod.VersionsTab })),
  { loading: TabSkeleton },
);

const ExportsTab = dynamic(
  () => import("~/components/estimates/tabs/ExportsTab.js").then((mod) => ({ default: mod.ExportsTab })),
  { loading: TabSkeleton },
);

const CommentThread = dynamic(
  () => import("~/components/comments/CommentThread.js").then((mod) => ({ default: mod.CommentThread })),
  { loading: TabSkeleton },
);

const TABS: Array<{ id: WorkspaceTab; label: string }> = [
  { id: "overview", label: "Overview" },
  { id: "assumptions", label: "Assumptions" },
  { id: "scope", label: "Scope Breakdown" },
  { id: "staffing", label: "Staffing" },
  { id: "financials", label: "Financials" },
  { id: "phasing", label: "Phasing" },
  { id: "versions", label: "Versions" },
  { id: "exports", label: "Exports" },
  { id: "comments", label: "Comments" },
];

function EmptyState({ children }: { children: React.ReactNode }) {
  return (
    <div className="rounded-3xl border border-dashed border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 px-5 py-10 text-center text-sm text-gray-400">
      {children}
    </div>
  );
}

function ActionNotice({
  tone,
  children,
}: {
  tone: "success" | "error";
  children: React.ReactNode;
}) {
  return (
    <div
      className={clsx(
        "rounded-2xl border px-4 py-3 text-sm",
        tone === "success"
          ? "border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-800 dark:bg-emerald-950/50 dark:text-emerald-300"
          : "border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-800 dark:bg-rose-950/50 dark:text-rose-300",
      )}
    >
      {children}
    </div>
  );
}

export function EstimateWorkspaceClient({ estimateId }: { estimateId: string }) {
  const { status: sessionStatus } = useSession();
  const [tab, setTab] = useState<WorkspaceTab>("overview");
  const [isEditing, setIsEditing] = useState(false);
  const [actionMessage, setActionMessage] = useState<string | null>(null);
  const [actionError, setActionError] = useState<string | null>(null);
  const { canEdit, canViewCosts } = usePermissions();
  const isPermissionsLoading = sessionStatus === "loading";
  const utils = trpc.useUtils();

  const detailQuery = trpc.estimate.getById.useQuery(
    { id: estimateId },
    {
      enabled: canViewCosts && !isPermissionsLoading,
      staleTime: 15_000,
    },
  );
  const submitVersionMutation = trpc.estimate.submitVersion.useMutation();
  const approveVersionMutation = trpc.estimate.approveVersion.useMutation();
  const createRevisionMutation = trpc.estimate.createRevision.useMutation();
  const createExportMutation = trpc.estimate.createExport.useMutation();
  const createPlanningHandoffMutation = trpc.estimate.createPlanningHandoff.useMutation();
  const estimateCommentTarget = { entityType: "estimate" as const, entityId: estimateId };
  const canLoadCommentCount =
    canViewCosts
    && !isPermissionsLoading
    && detailQuery.status === "success"
    && detailQuery.data != null;

  const commentCountQuery = trpc.comment.count.useQuery(
    estimateCommentTarget,
    { enabled: canLoadCommentCount, staleTime: 30_000 },
  );
  const commentCount = commentCountQuery.data ?? 0;

  const estimate = (detailQuery.data as EstimateWorkspaceView | undefined) ?? null;
  const hasWorkingVersion = estimate?.versions.some((version) => version.status === "WORKING") ?? false;
  const editableTab = tab === "overview" || tab === "assumptions" || tab === "scope" || tab === "staffing";

  useEffect(() => {
    setIsEditing(false);
    setActionError(null);
    setActionMessage(null);
  }, [estimateId]);

  async function invalidateEstimateData() {
    await Promise.all([
      utils.estimate.list.invalidate(),
      utils.estimate.getById.invalidate({ id: estimateId }),
    ]);
  }

  async function handleSubmitVersion(versionId: string) {
    setActionError(null);
    setActionMessage(null);

    try {
      await submitVersionMutation.mutateAsync({ estimateId, versionId });
      await invalidateEstimateData();
      setTab("versions");
      setIsEditing(false);
      setActionMessage("Working version submitted for review.");
    } catch (error) {
      setActionError(error instanceof Error ? error.message : "Failed to submit version.");
    }
  }

  async function handleApproveVersion(versionId: string) {
    setActionError(null);
    setActionMessage(null);

    try {
      await approveVersionMutation.mutateAsync({ estimateId, versionId });
      await invalidateEstimateData();
      setTab("versions");
      setIsEditing(false);
      setActionMessage("Submitted version approved and locked.");
    } catch (error) {
      setActionError(error instanceof Error ? error.message : "Failed to approve version.");
    }
  }

  async function handleCreateRevision(versionId: string) {
    setActionError(null);
    setActionMessage(null);

    try {
      await createRevisionMutation.mutateAsync({ estimateId, sourceVersionId: versionId });
      await invalidateEstimateData();
      setTab("versions");
      setActionMessage("New working revision created from the selected version.");
    } catch (error) {
      setActionError(error instanceof Error ? error.message : "Failed to create revision.");
    }
  }

  async function handleCreateExport(versionId: string, format: EstimateExportFormat) {
    setActionError(null);
    setActionMessage(null);

    try {
      await createExportMutation.mutateAsync({ estimateId, versionId, format });
      await invalidateEstimateData();
      setTab("exports");
      setActionMessage(`${format} export record created for the current version.`);
    } catch (error) {
      setActionError(error instanceof Error ? error.message : "Failed to create export.");
    }
  }

  async function handleCreatePlanningHandoff(versionId: string) {
    setActionError(null);
    setActionMessage(null);

    try {
      const result = await createPlanningHandoffMutation.mutateAsync({ estimateId, versionId });
      await invalidateEstimateData();
      setTab("versions");
      setActionMessage(
        `Planning handoff created ${result.createdCount} planning entr${result.createdCount === 1 ? "y" : "ies"} (${result.assignedCount} assigned, ${result.placeholderCount} open demand${result.placeholderCount === 1 ? "" : "s"}).`,
      );
    } catch (error) {
      setActionError(
        error instanceof Error
          ? error.message
          : "Failed to create planning allocations from the approved estimate.",
      );
    }
  }

  return (
    <div className="mx-auto max-w-7xl space-y-6 p-6">
      <Link
        href="/estimates"
        className="inline-flex items-center gap-1 text-sm text-gray-500 dark:text-gray-400 transition-colors hover:text-gray-800 dark:hover:text-gray-200"
      >
        <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
        </svg>
        Back to Estimates
      </Link>

      <div className="rounded-[28px] border border-gray-200 dark:border-gray-700 bg-gradient-to-br from-white via-white to-brand-50 dark:from-gray-900 dark:via-gray-900 dark:to-gray-900 p-6 shadow-sm dark:shadow-black/20">
        <div className="flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between">
          <div>
            <p className="text-xs font-semibold uppercase tracking-[0.24em] text-brand-600 dark:text-sky-400">Estimate Workspace <InfoTooltip content="Central workspace for inspecting and editing an estimate's scope, staffing, financials, and version history." /></p>
            <h1 className="mt-2 text-3xl font-semibold text-gray-900 dark:text-gray-50">
              {estimate?.name ?? "Loading estimate"}
            </h1>
            <p className="mt-2 max-w-3xl text-sm text-gray-600 dark:text-gray-300">
              Use the tabs below to inspect the connected estimate structure, version context, and staffing breakdown without relying on spreadsheet tabs.
            </p>
          </div>

          {estimate && (
            <div className="flex flex-col gap-3 lg:items-end">
              <div className="grid gap-2 text-sm text-gray-500 dark:text-gray-400 lg:text-right">
                <span>{estimate.project ? `${estimate.project.shortCode} - ${estimate.project.name}` : "Standalone estimate"}</span>
                <span>Updated {formatDateLong(estimate.updatedAt)}</span>
              </div>
              {canEdit && hasWorkingVersion && (
                <button
                  type="button"
                  onClick={() => {
                    if (!editableTab && !isEditing) return;
                    setIsEditing((current) => !current);
                  }}
                  className="rounded-2xl border border-brand-200 dark:border-sky-700 bg-white dark:bg-gray-800 px-4 py-2 text-sm font-semibold text-brand-700 dark:text-sky-300 transition hover:border-brand-300 dark:hover:border-sky-600 hover:bg-brand-50 dark:hover:bg-gray-700"
                >
                  {isEditing ? "Close editor" : editableTab ? "Edit working draft" : "Draft editor available in editable tabs"}
                </button>
              )}
            </div>
          )}
        </div>
      </div>

      {isPermissionsLoading ? (
        <EmptyState>Loading estimate workspace...</EmptyState>
      ) : !canViewCosts ? (
        <EmptyState>Your role can access the estimate list, but not the detailed financial workspace.</EmptyState>
      ) : detailQuery.isLoading ? (
        <EmptyState>Loading estimate workspace...</EmptyState>
      ) : detailQuery.error ? (
        <EmptyState>{detailQuery.error.message}</EmptyState>
      ) : !estimate ? (
        <EmptyState>Estimate not found.</EmptyState>
      ) : (
        <>
          {actionMessage && <ActionNotice tone="success">{actionMessage}</ActionNotice>}
          {actionError && <ActionNotice tone="error">{actionError}</ActionNotice>}

          <div className="flex flex-wrap gap-2 border-b border-gray-200 dark:border-gray-700">
            {TABS.map((item) => (
              <button
                key={item.id}
                type="button"
                onClick={() => setTab(item.id)}
                className={clsx(
                  "rounded-t-2xl border-b-2 px-4 py-3 text-sm font-medium transition-colors",
                  tab === item.id
                    ? "border-brand-600 text-brand-700 dark:border-sky-400 dark:text-sky-300"
                    : "border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200",
                )}
              >
                {item.label}
                {item.id === "comments" && commentCount > 0 && (
                  <span className="ml-1.5 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-brand-100 dark:bg-sky-800 px-1.5 text-xs font-semibold text-brand-700 dark:text-sky-200">
                    {commentCount}
                  </span>
                )}
              </button>
            ))}
          </div>

          {isEditing ? (
            <EstimateWorkspaceDraftEditor
              estimate={estimate}
              tab={tab}
              onCancel={() => setIsEditing(false)}
              onSaved={() => {
                setIsEditing(false);
              }}
            />
          ) : (
            <>
              {tab === "overview" && <OverviewTab estimate={estimate} />}
              {tab === "assumptions" && <AssumptionsTab estimate={estimate} />}
              {tab === "scope" && <ScopeTab estimate={estimate} />}
              {tab === "staffing" && <StaffingTab estimate={estimate} canEdit={canEdit} />}
              {tab === "financials" && <FinancialsTab estimate={estimate} canEdit={canEdit} />}
              {tab === "phasing" && (
                <WeeklyPhasingView estimateId={estimate.id} canEdit={canEdit} />
              )}
              {tab === "versions" && (
                <VersionsTab
                  estimate={estimate}
                  canEdit={canEdit}
                  hasLinkedProject={Boolean(estimate.projectId)}
                  onSubmitVersion={handleSubmitVersion}
                  onApproveVersion={handleApproveVersion}
                  onCreateRevision={handleCreateRevision}
                  onCreatePlanningHandoff={handleCreatePlanningHandoff}
                  isSubmitting={submitVersionMutation.isPending}
                  isApproving={approveVersionMutation.isPending}
                  isCreatingRevision={createRevisionMutation.isPending}
                  isCreatingPlanningHandoff={createPlanningHandoffMutation.isPending}
                />
              )}
              {tab === "exports" && (
                <ExportsTab
                  estimate={estimate}
                  canEdit={canEdit}
                  onCreateExport={handleCreateExport}
                  isCreatingExport={createExportMutation.isPending}
                />
              )}
              {tab === "comments" && (
                <div className="rounded-3xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-6">
                  <h2 className="mb-4 text-lg font-semibold text-gray-900 dark:text-gray-50">
                    Comments
                  </h2>
                  <CommentThread commentTarget={estimateCommentTarget} />
                </div>
              )}
            </>
          )}
        </>
      )}
    </div>
  );
}
