"use client";

import { useState, useEffect, useCallback } from "react";
import type { ReactElement, SyntheticEvent } from "react";
import { useRouter } from "next/navigation";
import { Plus, Trash2 } from "lucide-react";

import { MosaicSpinner } from "@/components/ui/MosaicSpinner";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { fetchProjects, createProject, deleteProject, ProjectStatus } from "@/lib/api/projects";
import type { Project, CreateProjectDto } from "@/lib/api/projects";
import { useWorkspaceId } from "@/lib/hooks";
import { fetchDomains } from "@/lib/api/domains";
import type { Domain } from "@mosaic/shared";

/* ---------------------------------------------------------------------------
   Status badge helpers
   --------------------------------------------------------------------------- */

interface StatusStyle {
  label: string;
  bg: string;
  color: string;
}

function getStatusStyle(status: ProjectStatus): StatusStyle {
  switch (status) {
    case ProjectStatus.PLANNING:
      return { label: "Planning", bg: "rgba(47,128,255,0.15)", color: "var(--primary)" };
    case ProjectStatus.ACTIVE:
      return { label: "Active", bg: "rgba(20,184,166,0.15)", color: "var(--success)" };
    case ProjectStatus.PAUSED:
      return { label: "Paused", bg: "rgba(245,158,11,0.15)", color: "var(--warn)" };
    case ProjectStatus.COMPLETED:
      return { label: "Completed", bg: "rgba(139,92,246,0.15)", color: "var(--purple)" };
    case ProjectStatus.ARCHIVED:
      return { label: "Archived", bg: "rgba(143,157,183,0.15)", color: "var(--muted)" };
    default:
      return { label: String(status), bg: "rgba(143,157,183,0.15)", color: "var(--muted)" };
  }
}

function formatTimestamp(iso: string): string {
  try {
    return new Date(iso).toLocaleDateString("en-US", {
      month: "short",
      day: "numeric",
      year: "numeric",
    });
  } catch {
    return iso;
  }
}

/* ---------------------------------------------------------------------------
   ProjectCard
   --------------------------------------------------------------------------- */

interface ProjectCardProps {
  project: Project;
  onDelete: (id: string) => void;
  onClick: (id: string) => void;
  domains: Domain[];
}

function ProjectCard({ project, onDelete, onClick, domains }: ProjectCardProps): ReactElement {
  const [hovered, setHovered] = useState(false);
  const status = getStatusStyle(project.status);
  // Find domain if project has a domainId
  const domain = project.domainId ? domains.find((d) => d.id === project.domainId) : undefined;

  return (
    <div
      role="button"
      tabIndex={0}
      onClick={() => {
        onClick(project.id);
      }}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          onClick(project.id);
        }
      }}
      onMouseEnter={() => {
        setHovered(true);
      }}
      onMouseLeave={() => {
        setHovered(false);
      }}
      style={{
        background: "var(--surface)",
        border: `1px solid ${hovered ? "var(--primary)" : "var(--border)"}`,
        borderRadius: "var(--r-lg)",
        padding: 20,
        cursor: "pointer",
        transition: "border-color 0.2s var(--ease)",
        display: "flex",
        flexDirection: "column",
        gap: 12,
        position: "relative",
      }}
    >
      {/* Header row: name + delete button */}
      <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between" }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <h3
            style={{
              fontWeight: 600,
              color: "var(--text)",
              fontSize: "1rem",
              margin: 0,
              overflow: "hidden",
              textOverflow: "ellipsis",
              whiteSpace: "nowrap",
            }}
          >
            {project.name}
          </h3>
        </div>

        {/* Delete button */}
        <button
          aria-label={`Delete project ${project.name}`}
          onClick={(e) => {
            e.stopPropagation();
            onDelete(project.id);
          }}
          onKeyDown={(e) => {
            e.stopPropagation();
          }}
          style={{
            background: "transparent",
            border: "none",
            cursor: "pointer",
            padding: 4,
            borderRadius: "var(--r-sm)",
            color: "var(--muted)",
            transition: "color 0.15s, background 0.15s",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            flexShrink: 0,
            marginLeft: 8,
          }}
          onMouseEnter={(e) => {
            e.currentTarget.style.color = "var(--danger)";
            e.currentTarget.style.background = "rgba(229,72,77,0.1)";
          }}
          onMouseLeave={(e) => {
            e.currentTarget.style.color = "var(--muted)";
            e.currentTarget.style.background = "transparent";
          }}
        >
          <Trash2 size={16} />
        </button>
      </div>

      {/* Description */}
      {project.description ? (
        <p
          style={{
            color: "var(--muted)",
            fontSize: "0.85rem",
            margin: 0,
            overflow: "hidden",
            textOverflow: "ellipsis",
            display: "-webkit-box",
            WebkitLineClamp: 2,
            WebkitBoxOrient: "vertical",
            lineHeight: 1.5,
          }}
        >
          {project.description}
        </p>
      ) : (
        <p style={{ color: "var(--muted)", fontSize: "0.85rem", margin: 0, fontStyle: "italic" }}>
          No description
        </p>
      )}

      {/* Footer: status + timestamps */}
      <div
        style={{
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          marginTop: "auto",
        }}
      >
        {/* Status badge */}
        <span
          style={{
            display: "inline-block",
            padding: "2px 10px",
            borderRadius: "var(--r)",
            background: status.bg,
            color: status.color,
            fontSize: "0.75rem",
            fontWeight: 500,
          }}
        >
          {status.label}
        </span>
        {domain && (
          <span
            style={{
              display: "inline-block",
              padding: "2px 10px",
              borderRadius: "var(--r)",
              background: "rgba(139,92,246,0.15)",
              color: "var(--purple)",
              fontSize: "0.75rem",
              fontWeight: 500,
              marginLeft: 8,
            }}
          >
            {domain.name}
          </span>
        )}

        {/* Timestamps */}
        <span
          style={{
            fontSize: "0.75rem",
            color: "var(--muted)",
            fontFamily: "var(--mono)",
          }}
        >
          {formatTimestamp(project.createdAt)}
        </span>
      </div>
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Create Project Dialog
   --------------------------------------------------------------------------- */

interface CreateDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (data: CreateProjectDto) => Promise<void>;
  isSubmitting: boolean;
  domains: Domain[];
}

function CreateProjectDialog({
  open,
  onOpenChange,
  onSubmit,
  isSubmitting,
  domains,
}: CreateDialogProps): ReactElement {
  const [name, setName] = useState("");
  const [description, setDescription] = useState("");
  const [formError, setFormError] = useState<string | null>(null);
  const [domainId, setDomainId] = useState("");

  function resetForm(): void {
    setName("");
    setDescription("");
    setFormError(null);
    setDomainId("");
  }

  async function handleSubmit(e: SyntheticEvent): Promise<void> {
    e.preventDefault();
    setFormError(null);
    setDomainId("");

    const trimmedName = name.trim();
    if (!trimmedName) {
      setFormError("Project name is required.");
      return;
    }

    try {
      const payload: CreateProjectDto = { name: trimmedName };
      const trimmedDesc = description.trim();
      if (trimmedDesc) {
        payload.description = trimmedDesc;
      }
      if (domainId) {
        payload.domainId = domainId;
      }
      await onSubmit(payload);
      resetForm();
    } catch (err: unknown) {
      setFormError(err instanceof Error ? err.message : "Failed to create project.");
    }
  }

  return (
    <Dialog
      open={open}
      onOpenChange={(isOpen) => {
        if (!isOpen) resetForm();
        onOpenChange(isOpen);
      }}
    >
      <DialogContent>
        <div
          style={{
            background: "var(--surface)",
            borderRadius: "var(--r-lg)",
            border: "1px solid var(--border)",
            padding: 24,
            position: "relative",
          }}
        >
          <DialogHeader>
            <DialogTitle>
              <span style={{ color: "var(--text)" }}>New Project</span>
            </DialogTitle>
            <DialogDescription>
              <span style={{ color: "var(--muted)" }}>
                Give your project a name and optional description.
              </span>
            </DialogDescription>
          </DialogHeader>

          <form
            onSubmit={(e) => {
              void handleSubmit(e);
            }}
            style={{ marginTop: 16 }}
          >
            {/* Name */}
            <div style={{ marginBottom: 16 }}>
              <label
                htmlFor="project-name"
                style={{
                  display: "block",
                  marginBottom: 6,
                  fontSize: "0.85rem",
                  fontWeight: 500,
                  color: "var(--text-2)",
                }}
              >
                Name <span style={{ color: "var(--danger)" }}>*</span>
              </label>
              <input
                id="project-name"
                type="text"
                value={name}
                onChange={(e) => {
                  setName(e.target.value);
                }}
                placeholder="e.g. Website Redesign"
                maxLength={255}
                autoFocus
                style={{
                  width: "100%",
                  padding: "8px 12px",
                  background: "var(--bg)",
                  border: "1px solid var(--border)",
                  borderRadius: "var(--r)",
                  color: "var(--text)",
                  fontSize: "0.9rem",
                  outline: "none",
                  boxSizing: "border-box",
                }}
              />
            </div>

            {/* Description */}
            <div style={{ marginBottom: 16 }}>
              <label
                htmlFor="project-description"
                style={{
                  display: "block",
                  marginBottom: 6,
                  fontSize: "0.85rem",
                  fontWeight: 500,
                  color: "var(--text-2)",
                }}
              >
                Description
              </label>
              <textarea
                id="project-description"
                value={description}
                onChange={(e) => {
                  setDescription(e.target.value);
                }}
                placeholder="A brief summary of this project..."
                rows={3}
                maxLength={10000}
                style={{
                  width: "100%",
                  padding: "8px 12px",
                  background: "var(--bg)",
                  border: "1px solid var(--border)",
                  borderRadius: "var(--r)",
                  color: "var(--text)",
                  fontSize: "0.9rem",
                  outline: "none",
                  resize: "vertical",
                  fontFamily: "inherit",
                  boxSizing: "border-box",
                }}
              />
            </div>

            {/* Domain */}
            <div style={{ marginBottom: 16 }}>
              <label
                htmlFor="project-domain"
                style={{
                  display: "block",
                  marginBottom: 6,
                  fontSize: "0.85rem",
                  fontWeight: 500,
                  color: "var(--text-2)",
                }}
              >
                Domain (optional)
              </label>
              <select
                id="project-domain"
                value={domainId}
                onChange={(e) => {
                  setDomainId(e.target.value);
                }}
                style={{
                  width: "100%",
                  padding: "8px 12px",
                  background: "var(--bg)",
                  border: "1px solid var(--border)",
                  borderRadius: "var(--r)",
                  color: "var(--text)",
                  fontSize: "0.9rem",
                  outline: "none",
                  boxSizing: "border-box",
                }}
              >
                <option value="">None</option>
                {domains.map((d) => (
                  <option key={d.id} value={d.id}>
                    {d.name}
                  </option>
                ))}
              </select>
            </div>

            {/* Form error */}
            {formError !== null && (
              <p style={{ color: "var(--danger)", fontSize: "0.85rem", margin: "0 0 12px" }}>
                {formError}
              </p>
            )}

            <DialogFooter>
              <button
                type="button"
                onClick={() => {
                  onOpenChange(false);
                }}
                disabled={isSubmitting}
                style={{
                  padding: "8px 16px",
                  background: "transparent",
                  border: "1px solid var(--border)",
                  borderRadius: "var(--r)",
                  color: "var(--text-2)",
                  fontSize: "0.85rem",
                  cursor: "pointer",
                }}
              >
                Cancel
              </button>
              <button
                type="submit"
                disabled={isSubmitting || !name.trim()}
                style={{
                  padding: "8px 16px",
                  background: "var(--primary)",
                  border: "none",
                  borderRadius: "var(--r)",
                  color: "#fff",
                  fontSize: "0.85rem",
                  fontWeight: 500,
                  cursor: isSubmitting || !name.trim() ? "not-allowed" : "pointer",
                  opacity: isSubmitting || !name.trim() ? 0.6 : 1,
                }}
              >
                {isSubmitting ? "Creating..." : "Create Project"}
              </button>
            </DialogFooter>
          </form>
        </div>
      </DialogContent>
    </Dialog>
  );
}

/* ---------------------------------------------------------------------------
   Delete Confirmation Dialog
   --------------------------------------------------------------------------- */

interface DeleteDialogProps {
  open: boolean;
  projectName: string;
  onConfirm: () => void;
  onCancel: () => void;
  isDeleting: boolean;
}

function DeleteConfirmDialog({
  open,
  projectName,
  onConfirm,
  onCancel,
  isDeleting,
}: DeleteDialogProps): ReactElement {
  return (
    <Dialog
      open={open}
      onOpenChange={(isOpen) => {
        if (!isOpen) onCancel();
      }}
    >
      <DialogContent>
        <div
          style={{
            background: "var(--surface)",
            borderRadius: "var(--r-lg)",
            border: "1px solid var(--border)",
            padding: 24,
          }}
        >
          <DialogHeader>
            <DialogTitle>
              <span style={{ color: "var(--text)" }}>Delete Project</span>
            </DialogTitle>
            <DialogDescription>
              <span style={{ color: "var(--muted)" }}>
                {"This will permanently delete "}
                <strong style={{ color: "var(--text)" }}>{projectName}</strong>
                {". This action cannot be undone."}
              </span>
            </DialogDescription>
          </DialogHeader>

          <DialogFooter>
            <button
              type="button"
              onClick={onCancel}
              disabled={isDeleting}
              style={{
                padding: "8px 16px",
                background: "transparent",
                border: "1px solid var(--border)",
                borderRadius: "var(--r)",
                color: "var(--text-2)",
                fontSize: "0.85rem",
                cursor: "pointer",
              }}
            >
              Cancel
            </button>
            <button
              type="button"
              onClick={onConfirm}
              disabled={isDeleting}
              style={{
                padding: "8px 16px",
                background: "var(--danger)",
                border: "none",
                borderRadius: "var(--r)",
                color: "#fff",
                fontSize: "0.85rem",
                fontWeight: 500,
                cursor: isDeleting ? "not-allowed" : "pointer",
                opacity: isDeleting ? 0.6 : 1,
              }}
            >
              {isDeleting ? "Deleting..." : "Delete"}
            </button>
          </DialogFooter>
        </div>
      </DialogContent>
    </Dialog>
  );
}

/* ---------------------------------------------------------------------------
   Projects Page
   --------------------------------------------------------------------------- */

export default function ProjectsPage(): ReactElement {
  const router = useRouter();
  const workspaceId = useWorkspaceId();

  const [projects, setProjects] = useState<Project[]>([]);
  const [domains, setDomains] = useState<Domain[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Create dialog state
  const [createOpen, setCreateOpen] = useState(false);
  const [isCreating, setIsCreating] = useState(false);

  // Delete dialog state
  const [deleteTarget, setDeleteTarget] = useState<Project | null>(null);
  const [isDeleting, setIsDeleting] = useState(false);

  const loadProjects = useCallback(async (wsId: string | null): Promise<void> => {
    try {
      setIsLoading(true);
      setError(null);
      const data = await fetchProjects(wsId ?? undefined);
      setProjects(data);
    } catch (err: unknown) {
      console.error("[Projects] Failed to fetch projects:", err);
      setError(
        err instanceof Error
          ? err.message
          : "Something went wrong loading projects. You could try again when ready."
      );
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!workspaceId) {
      setIsLoading(false);
      return;
    }

    let cancelled = false;
    const wsId = workspaceId;

    async function load(): Promise<void> {
      try {
        setIsLoading(true);
        setError(null);
        const data = await fetchProjects(wsId);
        if (!cancelled) {
          setProjects(data);
        }
      } catch (err: unknown) {
        console.error("[Projects] Failed to fetch projects:", err);
        if (!cancelled) {
          setError(
            err instanceof Error
              ? err.message
              : "Something went wrong loading projects. You could try again when ready."
          );
        }
      } finally {
        if (!cancelled) {
          setIsLoading(false);
        }
      }
    }

    void load();

    return (): void => {
      cancelled = true;
    };
  }, [workspaceId]);

  // Load domains
  useEffect(() => {
    if (!workspaceId) {
      return;
    }

    let cancelled = false;
    const wsId = workspaceId;

    async function loadDomains(): Promise<void> {
      try {
        const response = await fetchDomains(undefined, wsId);
        if (!cancelled) {
          setDomains(response.data);
        }
      } catch (err: unknown) {
        console.error("[Projects] Failed to fetch domains:", err);
      }
    }

    void loadDomains();

    return (): void => {
      cancelled = true;
    };
  }, [workspaceId]);

  function handleRetry(): void {
    void loadProjects(workspaceId);
  }

  async function handleCreate(data: CreateProjectDto): Promise<void> {
    setIsCreating(true);
    try {
      await createProject(data, workspaceId ?? undefined);
      setCreateOpen(false);
      void loadProjects(workspaceId);
    } finally {
      setIsCreating(false);
    }
  }

  function handleDeleteRequest(projectId: string): void {
    const target = projects.find((p) => p.id === projectId);
    if (target) {
      setDeleteTarget(target);
    }
  }

  async function handleDeleteConfirm(): Promise<void> {
    if (!deleteTarget) return;
    setIsDeleting(true);
    try {
      await deleteProject(deleteTarget.id, workspaceId ?? undefined);
      setDeleteTarget(null);
      void loadProjects(workspaceId);
    } catch (err: unknown) {
      console.error("[Projects] Failed to delete project:", err);
      setError(err instanceof Error ? err.message : "Failed to delete project.");
      setDeleteTarget(null);
    } finally {
      setIsDeleting(false);
    }
  }

  function handleCardClick(projectId: string): void {
    router.push(`/projects/${projectId}`);
  }

  return (
    <main className="container mx-auto px-4 py-8" style={{ maxWidth: 960 }}>
      {/* Header */}
      <div
        style={{
          display: "flex",
          alignItems: "flex-start",
          justifyContent: "space-between",
          marginBottom: 32,
          flexWrap: "wrap",
          gap: 16,
        }}
      >
        <div>
          <h1
            style={{
              fontSize: "1.875rem",
              fontWeight: 700,
              color: "var(--text)",
              margin: 0,
            }}
          >
            Projects
          </h1>
          <p
            style={{
              fontSize: "0.9rem",
              color: "var(--muted)",
              marginTop: 4,
            }}
          >
            Organize and track your work across different initiatives
          </p>
        </div>

        <button
          onClick={() => {
            setCreateOpen(true);
          }}
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 8,
            padding: "8px 16px",
            background: "var(--primary)",
            border: "none",
            borderRadius: "var(--r)",
            color: "#fff",
            fontSize: "0.85rem",
            fontWeight: 500,
            cursor: "pointer",
          }}
        >
          <Plus size={16} />
          New Project
        </button>
      </div>

      {/* Loading */}
      {isLoading ? (
        <div className="flex justify-center py-16">
          <MosaicSpinner label="Loading projects..." />
        </div>
      ) : error !== null ? (
        /* Error */
        <div
          style={{
            background: "var(--surface)",
            border: "1px solid var(--border)",
            borderRadius: "var(--r-lg)",
            padding: 32,
            textAlign: "center",
          }}
        >
          <p style={{ color: "var(--danger)", margin: "0 0 16px" }}>{error}</p>
          <button
            onClick={handleRetry}
            style={{
              padding: "8px 16px",
              background: "var(--danger)",
              border: "none",
              borderRadius: "var(--r)",
              color: "#fff",
              fontSize: "0.85rem",
              fontWeight: 500,
              cursor: "pointer",
            }}
          >
            Try again
          </button>
        </div>
      ) : projects.length === 0 ? (
        /* Empty */
        <div
          style={{
            background: "var(--surface)",
            border: "1px solid var(--border)",
            borderRadius: "var(--r-lg)",
            padding: 48,
            textAlign: "center",
          }}
        >
          <p style={{ color: "var(--muted)", margin: "0 0 16px", fontSize: "0.9rem" }}>
            No projects yet. Create your first project to get started.
          </p>
          <button
            onClick={() => {
              setCreateOpen(true);
            }}
            style={{
              display: "inline-flex",
              alignItems: "center",
              gap: 8,
              padding: "8px 16px",
              background: "var(--primary)",
              border: "none",
              borderRadius: "var(--r)",
              color: "#fff",
              fontSize: "0.85rem",
              fontWeight: 500,
              cursor: "pointer",
            }}
          >
            <Plus size={16} />
            Create Project
          </button>
        </div>
      ) : (
        /* Projects grid */
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          {projects.map((project) => (
            <ProjectCard
              key={project.id}
              project={project}
              onDelete={handleDeleteRequest}
              onClick={handleCardClick}
              domains={domains}
            />
          ))}
        </div>
      )}

      {/* Create Dialog */}
      <CreateProjectDialog
        open={createOpen}
        onOpenChange={setCreateOpen}
        onSubmit={handleCreate}
        isSubmitting={isCreating}
        domains={domains}
      />

      {/* Delete Confirmation Dialog */}
      <DeleteConfirmDialog
        open={deleteTarget !== null}
        projectName={deleteTarget?.name ?? ""}
        onConfirm={() => {
          void handleDeleteConfirm();
        }}
        onCancel={() => {
          setDeleteTarget(null);
        }}
        isDeleting={isDeleting}
      />
    </main>
  );
}
