'use client';
import { formatErrorBanner } from '@/lib/api/toast-error';
import { formatEnum } from '@/lib/constants';

import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Checkbox } from '@/components/ui/checkbox';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from '@/components/ui/sheet';
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from '@/components/ui/accordion';
import { apiFetch } from '@/lib/api/client';

/** Default permissions structure matching RolePermissions type in
 *  src/lib/db/schema/users.ts. Keep this in sync when actions are added. */
const DEFAULT_PERMISSIONS: Record<string, Record<string, boolean>> = {
  clients: { view: false, create: false, edit: false, delete: false, merge: false, export: false },
  interests: {
    view: false,
    create: false,
    edit: false,
    delete: false,
    change_stage: false,
    override_stage: false,
    generate_eoi: false,
    export: false,
  },
  berths: {
    view: false,
    edit: false,
    import: false,
    manage_waiting_list: false,
    update_prices: false,
  },
  documents: {
    view: false,
    create: false,
    edit: false,
    send_for_signing: false,
    upload_signed: false,
    delete: false,
    manage_folders: false,
  },
  expenses: {
    view: false,
    create: false,
    edit: false,
    delete: false,
    export: false,
    scan_receipt: false,
  },
  invoices: {
    view: false,
    create: false,
    edit: false,
    delete: false,
    send: false,
    record_payment: false,
    export: false,
  },
  payments: { view: false, record: false, delete: false },
  files: { view: false, upload: false, edit: false, delete: false, manage_folders: false },
  email: { view: false, send: false, configure_account: false },
  reminders: {
    view_own: false,
    view_all: false,
    create: false,
    edit_own: false,
    edit_all: false,
    assign_others: false,
  },
  calendar: { connect: false, view_events: false },
  reports: { view_dashboard: false, view_analytics: false, export: false },
  document_templates: { view: false, generate: false, manage: false },
  yachts: { view: false, create: false, edit: false, delete: false, transfer: false },
  companies: { view: false, create: false, edit: false, delete: false },
  memberships: { view: false, manage: false },
  tenancies: { view: false, manage: false, cancel: false },
  admin: {
    manage_users: false,
    view_audit_log: false,
    manage_settings: false,
    manage_webhooks: false,
    manage_reports: false,
    manage_custom_fields: false,
    manage_forms: false,
    manage_tags: false,
    system_backup: false,
    permanently_delete_clients: false,
  },
  residential_clients: { view: false, create: false, edit: false, delete: false },
  residential_interests: {
    view: false,
    create: false,
    edit: false,
    delete: false,
    change_stage: false,
  },
  inquiries: {
    view: false,
    manage: false,
  },
};

const GROUP_LABELS: Record<string, string> = {
  clients: 'Clients',
  interests: 'Interests / Pipeline',
  berths: 'Berths',
  documents: 'Documents',
  expenses: 'Expenses',
  invoices: 'Invoices',
  payments: 'Payments',
  files: 'Files',
  email: 'Email',
  reminders: 'Reminders',
  calendar: 'Calendar',
  reports: 'Reports',
  document_templates: 'Document Templates',
  yachts: 'Yachts',
  companies: 'Companies',
  memberships: 'Company Memberships',
  tenancies: 'Tenancies',
  admin: 'Administration',
  residential_clients: 'Residential Clients',
  residential_interests: 'Residential Interests',
  inquiries: 'Inquiries',
};

function formatAction(action: string): string {
  return formatEnum(action);
}

interface RoleFormProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  role?: {
    id: string;
    name: string;
    description: string | null;
    isSystem: boolean;
    permissions: Record<string, Record<string, boolean>>;
  } | null;
  onSuccess: () => void;
}

export function RoleForm(props: RoleFormProps) {
  return (
    <RoleFormBody key={props.open ? `open:${props.role?.id ?? 'new'}` : 'closed'} {...props} />
  );
}

function RoleFormBody({ open, onOpenChange, role, onSuccess }: RoleFormProps) {
  // Merge role permissions over defaults to fill any missing keys.
  const initialPermissions = (() => {
    const merged = structuredClone(DEFAULT_PERMISSIONS);
    if (role) {
      for (const [group, actions] of Object.entries(role.permissions)) {
        if (merged[group]) {
          for (const [action, value] of Object.entries(actions as Record<string, boolean>)) {
            merged[group]![action] = value;
          }
        }
      }
    }
    return merged;
  })();
  const [name, setName] = useState(role?.name ?? '');
  const [description, setDescription] = useState(role?.description ?? '');
  const [permissions, setPermissions] =
    useState<Record<string, Record<string, boolean>>>(initialPermissions);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const isEdit = !!role;

  function togglePermission(group: string, action: string) {
    setPermissions((prev) => {
      const next = structuredClone(prev);
      next[group]![action] = !next[group]![action];
      return next;
    });
  }

  function toggleGroup(group: string, value: boolean) {
    setPermissions((prev) => {
      const next = structuredClone(prev);
      for (const action of Object.keys(next[group]!)) {
        next[group]![action] = value;
      }
      return next;
    });
  }

  function isGroupAllChecked(group: string): boolean {
    return Object.values(permissions[group]!).every(Boolean);
  }

  function isGroupPartial(group: string): boolean {
    const vals = Object.values(permissions[group]!);
    return vals.some(Boolean) && !vals.every(Boolean);
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    setLoading(true);

    try {
      if (isEdit) {
        await apiFetch(`/api/v1/admin/roles/${role.id}`, {
          method: 'PATCH',
          body: { name, description: description || null, permissions },
        });
      } else {
        await apiFetch('/api/v1/admin/roles', {
          method: 'POST',
          body: { name, description: description || undefined, permissions },
        });
      }
      onSuccess();
      onOpenChange(false);
    } catch (err: unknown) {
      const message = formatErrorBanner(err);
      setError(message);
    } finally {
      setLoading(false);
    }
  }

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="w-[500px] sm:max-w-[500px]">
        <SheetHeader>
          <SheetTitle>{isEdit ? 'Edit Role' : 'New Role'}</SheetTitle>
        </SheetHeader>

        <form onSubmit={handleSubmit} className="mt-6 flex flex-col h-[calc(100vh-140px)]">
          <div className="space-y-4 mb-4">
            <div className="space-y-2">
              <Label htmlFor="role-name">Name</Label>
              <Input
                id="role-name"
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder="e.g. Sales Manager"
                required
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="role-description">Description</Label>
              <Textarea
                id="role-description"
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                placeholder="What this role is for..."
                rows={2}
              />
            </div>
          </div>

          <Label className="mb-2">Permissions</Label>
          <ScrollArea className="flex-1 rounded-md border">
            <Accordion type="multiple" className="px-3">
              {Object.entries(permissions).map(([group, actions]) => (
                <AccordionItem key={group} value={group}>
                  <AccordionTrigger className="text-sm">
                    <div className="flex items-center gap-3">
                      <Checkbox
                        checked={isGroupAllChecked(group)}
                        ref={(el) => {
                          if (el) {
                            (el as unknown as HTMLInputElement).indeterminate =
                              isGroupPartial(group);
                          }
                        }}
                        onCheckedChange={(checked) => toggleGroup(group, checked === true)}
                        onClick={(e) => e.stopPropagation()}
                      />
                      <span>{GROUP_LABELS[group] ?? group}</span>
                    </div>
                  </AccordionTrigger>
                  <AccordionContent>
                    <div className="grid grid-cols-2 gap-2 pl-8 pb-2">
                      {Object.entries(actions).map(([action, checked]) => (
                        <label
                          key={action}
                          className="flex items-center gap-2 text-sm cursor-pointer"
                        >
                          <Checkbox
                            checked={checked}
                            onCheckedChange={() => togglePermission(group, action)}
                          />
                          {formatAction(action)}
                        </label>
                      ))}
                    </div>
                  </AccordionContent>
                </AccordionItem>
              ))}
            </Accordion>
          </ScrollArea>

          {error && <p className="mt-2 whitespace-pre-line text-sm text-destructive">{error}</p>}

          <SheetFooter className="mt-4">
            <Button
              type="button"
              variant="outline"
              onClick={() => onOpenChange(false)}
              disabled={loading}
            >
              Cancel
            </Button>
            <Button type="submit" disabled={loading || !name.trim()}>
              {loading ? 'Saving…' : isEdit ? 'Save changes' : 'Create Role'}
            </Button>
          </SheetFooter>
        </form>
      </SheetContent>
    </Sheet>
  );
}
