import { useState } from 'react';
import { Link, useNavigate } from 'react-router';
import { FolderKanban, Plus, ArrowRight, Type, Rocket, FileText, Layout, Loader2 } from 'lucide-react';
import { useQueryClient } from '@tanstack/react-query';
import { useGlobal } from 'hooks/useGlobal';
import { useClient } from 'hooks/useClient';
import { useDashboardState } from 'state/useDashboardState';
import { WorkspaceLayout, WorkspaceView, createDefaultLayout } from '../../components/Workspace';
import type { LayoutNode, ProjectDefinition, ProjectType } from '../../components/Workspace';
import { Button } from '@/components/ui/button';
import { generateSlug, slugify } from 'helpers/slug';
import { useAppRegistry } from '../../AppRegistry';
import {
  SELECTED_PROJECT,
  CREATING_PROJECT,
  EDITING_PROJECT,
  NEW_PROJ_NAME,
  NEW_PROJ_DESC,
  NEW_PROJ_TEMPLATE,
  NEW_PROJ_TYPE,
  NEW_PROJ_HAS_BACKEND,
  NEW_PROJ_HAS_AUTH,
  NEW_PROJ_PREVIEW_LAYOUT,
} from './constants';

// --- Layout Templates ---

let tplCounter = 0;
const tplUid = () => `ptpl-${++tplCounter}`;

type LayoutTemplate = {
  name: string;
  layout: () => LayoutNode;
};

const templates: LayoutTemplate[] = [
  {
    name: '2 Columns',
    layout: () => ({
      type: 'group',
      id: tplUid(),
      direction: 'horizontal',
      children: [
        { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
        { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
      ],
    }),
  },
  {
    name: 'Main + Side',
    layout: () => ({
      type: 'group',
      id: tplUid(),
      direction: 'horizontal',
      children: [
        { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
        {
          node: {
            type: 'group',
            id: tplUid(),
            direction: 'vertical',
            children: [
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
            ],
          },
          size: 50,
        },
      ],
    }),
  },
  {
    name: 'Sidebar',
    layout: () => ({
      type: 'group',
      id: tplUid(),
      direction: 'horizontal',
      children: [
        { node: { type: 'panel', id: tplUid(), appType: null }, size: 25 },
        { node: { type: 'panel', id: tplUid(), appType: null }, size: 75 },
      ],
    }),
  },
  {
    name: '2x2 Grid',
    layout: () => ({
      type: 'group',
      id: tplUid(),
      direction: 'vertical',
      children: [
        {
          node: {
            type: 'group',
            id: tplUid(),
            direction: 'horizontal',
            children: [
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
            ],
          },
          size: 50,
        },
        {
          node: {
            type: 'group',
            id: tplUid(),
            direction: 'horizontal',
            children: [
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
            ],
          },
          size: 50,
        },
      ],
    }),
  },
  {
    name: 'Cols + Bottom',
    layout: () => ({
      type: 'group',
      id: tplUid(),
      direction: 'vertical',
      children: [
        {
          node: {
            type: 'group',
            id: tplUid(),
            direction: 'horizontal',
            children: [
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
            ],
          },
          size: 70,
        },
        { node: { type: 'panel', id: tplUid(), appType: null }, size: 30 },
      ],
    }),
  },
  {
    name: 'Cols + Split Bottom',
    layout: () => ({
      type: 'group',
      id: tplUid(),
      direction: 'vertical',
      children: [
        {
          node: {
            type: 'group',
            id: tplUid(),
            direction: 'horizontal',
            children: [
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
            ],
          },
          size: 70,
        },
        {
          node: {
            type: 'group',
            id: tplUid(),
            direction: 'horizontal',
            children: [
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
              { node: { type: 'panel', id: tplUid(), appType: null }, size: 50 },
            ],
          },
          size: 30,
        },
      ],
    }),
  },
];

// --- Template Thumbnails ---

const ThumbnailNode = ({ node }: { node: LayoutNode }) => {
  if (node.type === 'panel') {
    return <div className="h-full w-full bg-emerald-500/15 border border-emerald-500/20 rounded-sm" />;
  }
  const isH = node.direction === 'horizontal';
  return (
    <div className={`flex h-full w-full gap-1.5 ${isH ? 'flex-row' : 'flex-col'}`}>
      {node.children.map((child) => (
        <div key={child.node.id} style={{ flex: child.size }} className="min-h-0 min-w-0">
          <ThumbnailNode node={child.node} />
        </div>
      ))}
    </div>
  );
};

const TemplateCell = ({ index }: { index: number }) => {
  const tpl = templates[index]!;
  const [selected, setSelected] = useGlobal<number>(NEW_PROJ_TEMPLATE, 0);
  const node = tpl.layout();
  const isSelected = selected === index;

  return (
    <div className="h-full w-full">
      <button
        type="button"
        onClick={() => setSelected(index)}
        className={`flex h-full w-full flex-col items-center justify-center gap-2 p-3 cursor-pointer transition-colors ${
          isSelected ? 'bg-emerald-500/10' : 'hover:bg-duck-dark/5'
        }`}
      >
        <div className="w-full flex-1 min-h-0 rounded border border-duck-dark/20 overflow-hidden">
          <ThumbnailNode node={node} />
        </div>
        <span className={`text-xs font-medium ${isSelected ? 'text-emerald-400' : 'text-duck-dark/60'}`}>{tpl.name}</span>
      </button>
    </div>
  );
};

// --- Panel: Template Picker (3x2 workspace) ---

const tplPanelLayout: LayoutNode = {
  type: 'group',
  id: 'ptpl-root',
  direction: 'vertical',
  children: [
    {
      node: {
        type: 'group',
        id: 'ptpl-row-0',
        direction: 'horizontal',
        children: [
          { node: { type: 'panel', id: 'ptpl-0', appType: 'ptpl-0' }, size: 33.33 },
          { node: { type: 'panel', id: 'ptpl-1', appType: 'ptpl-1' }, size: 33.33 },
          { node: { type: 'panel', id: 'ptpl-2', appType: 'ptpl-2' }, size: 33.34 },
        ],
      },
      size: 50,
    },
    {
      node: {
        type: 'group',
        id: 'ptpl-row-1',
        direction: 'horizontal',
        children: [
          { node: { type: 'panel', id: 'ptpl-3', appType: 'ptpl-3' }, size: 33.33 },
          { node: { type: 'panel', id: 'ptpl-4', appType: 'ptpl-4' }, size: 33.33 },
          { node: { type: 'panel', id: 'ptpl-5', appType: 'ptpl-5' }, size: 33.34 },
        ],
      },
      size: 50,
    },
  ],
};

const tplRegistry = Object.fromEntries(
  templates.map((tpl, i) => [`ptpl-${i}`, { name: tpl.name, icon: Layout, component: () => <TemplateCell index={i} /> }]),
);

const TemplatePanel = () => (
  <WorkspaceLayout layout={tplPanelLayout} onLayoutChange={() => {}} registry={tplRegistry} noHeader />
);

// --- Panel: Details (Name + Description + Project Type + Backend/Auth toggles) ---

const PROJECT_TYPE_OPTIONS: { value: ProjectType; label: string }[] = [
  // { value: 'landing-page', label: 'Landing Page' },
  // { value: 'website', label: 'Website' },
  { value: 'app', label: 'App' },
];

const DetailsPanel = () => {
  const [name, setName] = useGlobal<string>(NEW_PROJ_NAME, '');
  const [description, setDescription] = useGlobal<string>(NEW_PROJ_DESC, '');
  const [projectType, setProjectType] = useGlobal<ProjectType>(NEW_PROJ_TYPE, 'app');
  const [hasBackend, setHasBackend] = useGlobal<boolean>(NEW_PROJ_HAS_BACKEND, false);
  const [hasAuth, setHasAuth] = useGlobal<boolean>(NEW_PROJ_HAS_AUTH, false);

  return (
    <div className="h-full w-full overflow-y-auto">
      <div className="flex h-full flex-col gap-4 p-4">
        <div className="flex flex-col gap-1.5">
          <label className="text-xs font-medium text-duck-dark/50 flex items-center gap-1.5">
            <Type className="h-3 w-3" />
            Name
          </label>
          <input
            type="text"
            value={name}
            onChange={(ev) => setName(ev.target.value)}
            placeholder="My Project"
            autoFocus
            className="rounded-lg border border-duck-dark/20 bg-background px-3 py-2 text-sm text-duck-dark placeholder:text-duck-dark/30 focus:outline-none focus:ring-2 focus:ring-emerald-500/30 focus:border-emerald-500/50"
          />
        </div>
        <div className="flex flex-col gap-1.5">
          <label className="text-xs font-medium text-duck-dark/50 flex items-center gap-1.5">
            <FileText className="h-3 w-3" />
            Description
          </label>
          <textarea
            value={description}
            onChange={(ev) => setDescription(ev.target.value)}
            placeholder="What is this project for?"
            rows={3}
            className="resize-none rounded-lg border border-duck-dark/20 bg-background px-3 py-2 text-sm text-duck-dark placeholder:text-duck-dark/30 focus:outline-none focus:ring-2 focus:ring-emerald-500/30 focus:border-emerald-500/50"
          />
        </div>
        <div className="flex flex-col gap-1.5">
          <label className="text-xs font-medium text-duck-dark/50">Project Type</label>
          <div className="flex gap-2">
            {PROJECT_TYPE_OPTIONS.map((opt) => (
              <button
                key={opt.value}
                type="button"
                onClick={() => setProjectType(opt.value)}
                className={`flex-1 py-1.5 px-2 rounded-lg text-xs font-medium border transition-colors cursor-pointer ${
                  projectType === opt.value
                    ? 'bg-emerald-500/15 border-emerald-500/40 text-emerald-400'
                    : 'border-duck-dark/20 text-duck-dark/50 hover:border-duck-dark/30'
                }`}
              >
                {opt.label}
              </button>
            ))}
          </div>
        </div>
        {/* {projectType === 'app' && (
          <div className="flex flex-col gap-2">
            <label className="flex items-center gap-2 cursor-pointer">
              <input
                type="checkbox"
                checked={hasBackend}
                onChange={(ev) => setHasBackend(ev.target.checked)}
                className="accent-emerald-500"
              />
              <span className="text-xs text-duck-dark/60">Has Backend</span>
            </label>
            <label className="flex items-center gap-2 cursor-pointer">
              <input
                type="checkbox"
                checked={hasAuth}
                onChange={(ev) => setHasAuth(ev.target.checked)}
                className="accent-emerald-500"
              />
              <span className="text-xs text-duck-dark/60">Has Auth</span>
            </label>
          </div>
        )} */}
      </div>
    </div>
  );
};

// --- Panel: Create ---

const assignDefaultApps = (layout: LayoutNode, apps: string[]): LayoutNode => {
  const remaining = [...apps];
  const walk = (node: LayoutNode): LayoutNode => {
    if (remaining.length === 0) return node;
    if (node.type === 'panel' && node.appType === null) {
      return { ...node, appType: remaining.shift()! };
    }
    if (node.type === 'group') {
      return { ...node, children: node.children.map((c) => ({ ...c, node: walk(c.node) })) };
    }
    return node;
  };
  return walk(layout);
};

const CreatePanel = () => {
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const client = useClient();
  const [name, setName] = useGlobal<string>(NEW_PROJ_NAME, '');
  const { value: projects } = useDashboardState<ProjectDefinition[]>('projects', []);

  const [description, setDescription] = useGlobal<string>(NEW_PROJ_DESC, '');
  const [templateIdx, setTemplateIdx] = useGlobal<number>(NEW_PROJ_TEMPLATE, 0);
  const [previewLayout] = useGlobal<LayoutNode>(NEW_PROJ_PREVIEW_LAYOUT, createDefaultLayout());
  const [projectType] = useGlobal<ProjectType>(NEW_PROJ_TYPE, 'app');
  const [hasBackend] = useGlobal<boolean>(NEW_PROJ_HAS_BACKEND, false);
  const [hasAuth] = useGlobal<boolean>(NEW_PROJ_HAS_AUTH, false);
  const [editingId, setEditingId] = useGlobal<string | null>(EDITING_PROJECT, null);
  const [, setCreating] = useGlobal<boolean>(CREATING_PROJECT, false);
  const [, setSelected] = useGlobal<string | null>(SELECTED_PROJECT, null);
  const [isSubmitting, setIsSubmitting] = useState(false);

  const isEditing = !!editingId;
  const slug = isEditing ? editingId : slugify(name.trim()) || generateSlug();

  const handleSubmit = async () => {
    const trimmed = name.trim();
    if (!trimmed || isSubmitting) return;
    const desc = description.trim();

    const meta = {
      name: trimmed,
      description: desc || undefined,
      projectType,
      hasBackend: projectType === 'app' ? hasBackend : undefined,
      hasAuth: projectType === 'app' ? hasAuth : undefined,
      templateIdx,
    };

    if (isEditing) {
      client
        .patch('/dashboards', { [`proj-meta-${editingId}`]: meta, [`proj-layout-${editingId}`]: previewLayout })
        .then((res) => queryClient.setQueryData(['DASHBOARD_STATE'], res))
        .catch(() => {});

      setEditingId(null);
      setSelected(editingId);
    } else {
      const existingIds = new Set(projects.map((p) => p.id));
      let id = slugify(trimmed) || generateSlug();
      while (existingIds.has(id)) id = `${id}-${generateSlug(1)}`;

      setIsSubmitting(true);
      const finalLayout = projectType === 'app'
        ? assignDefaultApps(previewLayout, ['officerdev/chat', 'officerdev/preview'])
        : previewLayout;

      try {
        const res = await client.patch('/dashboards', { [`proj-meta-${id}`]: meta, [`proj-layout-${id}`]: finalLayout });
        queryClient.setQueryData(['DASHBOARD_STATE'], res);
        setName('');
        setDescription('');
        setTemplateIdx(0);
        navigate(`/projects/${id}`);
      } catch {
        // ignore
      } finally {
        setIsSubmitting(false);
      }
    }
  };

  return (
    <div className="h-full w-full">
      <div className="flex h-full flex-col items-center justify-center gap-4 p-4">
        <Rocket className="h-8 w-8 text-emerald-500/40" />
        <div className="text-center">
          <p className="text-sm font-medium text-duck-dark/70">{name.trim() || 'Untitled'}</p>
          <p className="text-xs font-mono text-duck-dark/40 mt-1">~/Projects/{slug}</p>
        </div>
        <Button
          onClick={handleSubmit}
          disabled={!name.trim() || isSubmitting}
          className="bg-emerald-500 hover:bg-emerald-500/90 cursor-pointer disabled:opacity-40"
        >
          {isSubmitting ? <Loader2 className="h-4 w-4 mr-1 animate-spin" /> : <Plus className="h-4 w-4 mr-1" />}
          {isSubmitting ? 'Creating...' : isEditing ? 'Update Project' : 'Create Project'}
        </Button>
        {isEditing && (
          <Button
            onClick={() => navigate(`/projects/${editingId}`)}
            variant="outline"
            className="cursor-pointer"
          >
            <ArrowRight className="h-4 w-4 mr-1" />
            Open Project
          </Button>
        )}
      </div>
    </div>
  );
};

// --- Panel: Live Template Preview (full interactive sub-workspace) ---

const PREVIEW_LAYOUT_KEY = ['USE_GLOBAL', NEW_PROJ_PREVIEW_LAYOUT];

const TemplatePreviewInner = ({ templateIdx }: { templateIdx: number }) => {
  const queryClient = useQueryClient();
  const [layout, setLocalLayout] = useState<LayoutNode>(() => {
    const initial = templates[templateIdx]!.layout();
    queryClient.setQueryData(PREVIEW_LAYOUT_KEY, initial);
    return initial;
  });

  const handleLayoutChange = (next: LayoutNode) => {
    setLocalLayout(next);
    queryClient.setQueryData(PREVIEW_LAYOUT_KEY, next);
  };

  return <WorkspaceLayout layout={layout} onLayoutChange={handleLayoutChange} noHeader />;
};

const TemplatePreviewPanel = () => {
  const [selectedIdx] = useGlobal<number>(NEW_PROJ_TEMPLATE, 0);
  return <TemplatePreviewInner key={selectedIdx} templateIdx={selectedIdx} />;
};

// --- New Project Layout ---

const newProjLayout: LayoutNode = {
  type: 'group',
  id: 'new-proj-root',
  direction: 'vertical',
  children: [
    {
      node: {
        type: 'group',
        id: 'new-proj-top',
        direction: 'horizontal',
        children: [
          { node: { type: 'panel', id: 'new-proj-details', appType: 'new-proj-details' }, size: 30 },
          { node: { type: 'panel', id: 'new-proj-template', appType: 'new-proj-template' }, size: 70 },
        ],
      },
      size: 50,
    },
    {
      node: {
        type: 'group',
        id: 'new-proj-bottom',
        direction: 'horizontal',
        children: [
          { node: { type: 'panel', id: 'new-proj-placeholder', appType: 'new-proj-placeholder' }, size: 70 },
          { node: { type: 'panel', id: 'new-proj-create', appType: 'new-proj-create' }, size: 30 },
        ],
      },
      size: 50,
    },
  ],
};

const NewProjectForm = () => {
  const { registry } = useAppRegistry();
  const newProjRegistry = {
    ...registry,
    'new-proj-details': { name: 'Details', icon: Type, component: DetailsPanel },
    'new-proj-placeholder': { name: 'Preview', icon: Layout, component: TemplatePreviewPanel },
    'new-proj-template': { name: 'Template', icon: Layout, component: TemplatePanel },
    'new-proj-create': { name: 'Create', icon: Rocket, component: CreatePanel },
  };

  return <WorkspaceLayout layout={newProjLayout} onLayoutChange={() => {}} registry={newProjRegistry} noHeader />;
};

const ProjectPreviewEmpty = () => {
  const [creating, setCreating] = useGlobal<boolean>(CREATING_PROJECT, false);
  const [editingId] = useGlobal<string | null>(EDITING_PROJECT, null);
  const [, setName] = useGlobal<string>(NEW_PROJ_NAME, '');
  const [, setDescription] = useGlobal<string>(NEW_PROJ_DESC, '');
  const [, setTemplateIdx] = useGlobal<number>(NEW_PROJ_TEMPLATE, 0);
  const [, setProjectType] = useGlobal<ProjectType>(NEW_PROJ_TYPE, 'app');
  const [, setHasBackend] = useGlobal<boolean>(NEW_PROJ_HAS_BACKEND, false);
  const [, setHasAuth] = useGlobal<boolean>(NEW_PROJ_HAS_AUTH, false);

  if (creating || editingId) return <NewProjectForm />;

  const handleCreate = () => {
    setName(generateSlug());
    setDescription('');
    setTemplateIdx(0);
    setProjectType('app');
    setHasBackend(false);
    setHasAuth(false);
    setCreating(true);
  };

  return (
    <div className="h-full w-full">
      <div className="flex h-full w-full flex-col items-center justify-center gap-4">
        <FolderKanban className="h-10 w-10 text-white/80" />
        <p className="text-sm text-white/80">Select a project or create a new one</p>
        <Button onClick={handleCreate} className="bg-emerald-500 hover:bg-emerald-500/90 cursor-pointer">
          <Plus className="h-4 w-4 mr-1" />
          New Project
        </Button>
      </div>
    </div>
  );
};

const ProjectPreviewInner = ({ project }: { project: ProjectDefinition }) => {
  const ws = useDashboardState<LayoutNode>(`proj-layout-${project.id}`, createDefaultLayout());
  return <WorkspaceView workspace={ws} cwd={project.cwd} />;
};

export const ProjectPreview = () => {
  const [selectedId] = useGlobal<string | null>(SELECTED_PROJECT, null);
  const { value: projects } = useDashboardState<ProjectDefinition[]>('projects', []);
  const project = selectedId ? projects.find((p) => p.id === selectedId) : null;

  if (!project) return <ProjectPreviewEmpty />;

  return (
    <div className="relative h-full w-full">
      <ProjectPreviewInner key={project.id} project={project} />
      <Link
        to={`/projects/${project.id}`}
        className="absolute inset-0 z-10 flex items-center justify-center bg-transparent hover:bg-duck-dark/10 transition-colors group"
      >
        <ArrowRight className="h-16 w-16 text-emerald-500/0 group-hover:text-emerald-500/60 transition-colors" />
      </Link>
    </div>
  );
};
