'use client';

import * as React from 'react';
import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
import { toast } from 'sonner';
import { BUSINESS_ROLES } from '@/lib/auth/rbac';
import { Icons } from '@/components/icons';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Switch } from '@/components/ui/switch';
import { Textarea } from '@/components/ui/textarea';
import {
  activateApprovalWorkflowMutation,
  cloneApprovalWorkflowMutation,
  createApprovalWorkflowMutation,
  createApprovalWorkflowStepMutation,
  deactivateApprovalWorkflowMutation,
  deleteApprovalWorkflowMutation,
  deleteApprovalWorkflowStepMutation,
  reorderApprovalWorkflowStepsMutation,
  updateApprovalWorkflowMutation,
  updateApprovalWorkflowStepMutation
} from '../mutations';
import { approvalWorkflowByIdOptions, approvalWorkflowsQueryOptions } from '../queries';
import type {
  ApprovalStepMutationPayload,
  ApprovalStepRecord,
  ApprovalStepUpdatePayload,
  ApprovalWorkflowDetail,
  ApprovalWorkflowMutationPayload
} from '../types';

const APPROVAL_MODES = [
  { value: 'sequential', label: 'Sequential', description: 'Runs step-by-step in current runtime.' },
  { value: 'any_one', label: 'Any One', description: 'Stored for future runtime support.' },
  { value: 'all_required', label: 'All Required', description: 'Stored for future runtime support.' }
] as const;

type WorkflowFormState = {
  code: string;
  name: string;
  entityType: string;
  description: string;
  isActive: boolean;
};

type StepFormState = {
  stepNumber: string;
  roleCode: string;
  roleName: string;
  approvalMode: ApprovalStepMutationPayload['approvalMode'];
  isRequired: boolean;
};

function toWorkflowState(workflow?: ApprovalWorkflowDetail): WorkflowFormState {
  return {
    code: workflow?.code ?? '',
    name: workflow?.name ?? '',
    entityType: workflow?.entityType ?? 'quotation',
    description: workflow?.description ?? '',
    isActive: workflow?.isActive ?? true
  };
}

function toStepState(step?: ApprovalStepRecord, stepNumber = 1): StepFormState {
  return {
    stepNumber: String(step?.stepNumber ?? stepNumber),
    roleCode: step?.roleCode ?? 'sales_manager',
    roleName: step?.roleName ?? 'Sales Manager',
    approvalMode: step?.approvalMode ?? 'sequential',
    isRequired: step?.isRequired ?? true
  };
}

function friendlyRoleName(roleCode: string) {
  return roleCode
    .split('_')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ');
}

function WorkflowDialog({
  open,
  onOpenChange,
  workflow
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  workflow?: ApprovalWorkflowDetail;
}) {
  const [state, setState] = React.useState<WorkflowFormState>(toWorkflowState(workflow));
  const createMutation = useMutation({
    ...createApprovalWorkflowMutation,
    onSuccess: () => {
      toast.success('Workflow created');
      onOpenChange(false);
    },
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Create failed')
  });
  const updateMutation = useMutation({
    ...updateApprovalWorkflowMutation,
    onSuccess: () => {
      toast.success('Workflow updated');
      onOpenChange(false);
    },
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Update failed')
  });

  React.useEffect(() => {
    if (open) {
      setState(toWorkflowState(workflow));
    }
  }, [open, workflow]);

  const isPending = createMutation.isPending || updateMutation.isPending;

  async function onSubmit(event: React.FormEvent) {
    event.preventDefault();

    const payload: ApprovalWorkflowMutationPayload = {
      code: state.code,
      name: state.name,
      entityType: state.entityType,
      description: state.description.trim() || null,
      isActive: state.isActive
    };

    if (workflow) {
      await updateMutation.mutateAsync({ id: workflow.id, values: payload });
      return;
    }

    await createMutation.mutateAsync(payload);
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className='sm:max-w-2xl'>
        <DialogHeader>
          <DialogTitle>{workflow ? 'Edit Workflow' : 'Create Workflow'}</DialogTitle>
          <DialogDescription>
            Configure workflow metadata. Runtime still executes steps sequentially for now.
          </DialogDescription>
        </DialogHeader>

        <form onSubmit={onSubmit} className='space-y-4'>
          <div className='grid gap-4 md:grid-cols-2'>
            <div className='space-y-2'>
              <div className='text-sm font-medium'>Code</div>
              <Input
                placeholder='quotation_standard_approval'
                value={state.code}
                onChange={(event) => setState((current) => ({ ...current, code: event.target.value }))}
              />
            </div>
            <div className='space-y-2'>
              <div className='text-sm font-medium'>Entity Type</div>
              <Input
                placeholder='quotation'
                value={state.entityType}
                onChange={(event) =>
                  setState((current) => ({ ...current, entityType: event.target.value }))
                }
              />
            </div>
          </div>

          <div className='space-y-2'>
            <div className='text-sm font-medium'>Name</div>
            <Input
              placeholder='Quotation Standard Approval'
              value={state.name}
              onChange={(event) => setState((current) => ({ ...current, name: event.target.value }))}
            />
          </div>

          <div className='space-y-2'>
            <div className='text-sm font-medium'>Description</div>
            <Textarea
              placeholder='Describe when this workflow should be used'
              value={state.description}
              onChange={(event) =>
                setState((current) => ({ ...current, description: event.target.value }))
              }
            />
          </div>

          {!workflow ? (
            <div className='flex items-center justify-between rounded-lg border px-4 py-3'>
              <div>
                <div className='font-medium'>Active on creation</div>
                <div className='text-muted-foreground text-sm'>
                  Keep this off if you want to finish step configuration first.
                </div>
              </div>
              <Switch
                checked={state.isActive}
                onCheckedChange={(checked) => setState((current) => ({ ...current, isActive: checked }))}
              />
            </div>
          ) : null}

          <DialogFooter>
            <Button type='button' variant='outline' onClick={() => onOpenChange(false)}>
              Cancel
            </Button>
            <Button type='submit' isLoading={isPending}>
              {workflow ? 'Save Workflow' : 'Create Workflow'}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

function StepDialog({
  open,
  onOpenChange,
  workflow,
  step
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  workflow: ApprovalWorkflowDetail;
  step?: ApprovalStepRecord;
}) {
  const [state, setState] = React.useState<StepFormState>(toStepState(step, workflow.steps.length + 1));
  const createMutation = useMutation({
    ...createApprovalWorkflowStepMutation,
    onSuccess: () => {
      toast.success('Step created');
      onOpenChange(false);
    },
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Create failed')
  });
  const updateMutation = useMutation({
    ...updateApprovalWorkflowStepMutation,
    onSuccess: () => {
      toast.success('Step updated');
      onOpenChange(false);
    },
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Update failed')
  });

  React.useEffect(() => {
    if (open) {
      setState(toStepState(step, workflow.steps.length + 1));
    }
  }, [open, step, workflow.steps.length]);

  const isPending = createMutation.isPending || updateMutation.isPending;

  async function onSubmit(event: React.FormEvent) {
    event.preventDefault();

    if (step) {
      const payload: ApprovalStepUpdatePayload = {
        roleCode: state.roleCode,
        roleName: state.roleName,
        approvalMode: state.approvalMode,
        isRequired: state.isRequired
      };
      await updateMutation.mutateAsync({
        workflowId: workflow.id,
        stepId: step.id,
        values: payload
      });
      return;
    }

    const payload: ApprovalStepMutationPayload = {
      stepNumber: Number(state.stepNumber),
      roleCode: state.roleCode,
      roleName: state.roleName,
      approvalMode: state.approvalMode,
      isRequired: state.isRequired
    };
    await createMutation.mutateAsync({
      workflowId: workflow.id,
      values: payload
    });
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className='sm:max-w-2xl'>
        <DialogHeader>
          <DialogTitle>{step ? 'Edit Step' : 'Add Step'}</DialogTitle>
          <DialogDescription>
            Non-sequential approval modes are stored now for future runtime support.
          </DialogDescription>
        </DialogHeader>

        <form onSubmit={onSubmit} className='space-y-4'>
          {!step ? (
            <div className='space-y-2'>
              <div className='text-sm font-medium'>Step Number</div>
              <Input
                type='number'
                min={1}
                value={state.stepNumber}
                onChange={(event) =>
                  setState((current) => ({ ...current, stepNumber: event.target.value }))
                }
              />
            </div>
          ) : null}

          <div className='grid gap-4 md:grid-cols-2'>
            <div className='space-y-2'>
              <div className='text-sm font-medium'>Role Code</div>
              <select
                className='border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm'
                value={state.roleCode}
                onChange={(event) =>
                  setState((current) => ({
                    ...current,
                    roleCode: event.target.value,
                    roleName: friendlyRoleName(event.target.value)
                  }))
                }
              >
                {BUSINESS_ROLES.map((role) => (
                  <option key={role} value={role}>
                    {role}
                  </option>
                ))}
              </select>
            </div>
            <div className='space-y-2'>
              <div className='text-sm font-medium'>Role Name</div>
              <Input
                value={state.roleName}
                onChange={(event) =>
                  setState((current) => ({ ...current, roleName: event.target.value }))
                }
              />
            </div>
          </div>

          <div className='space-y-2'>
            <div className='text-sm font-medium'>Approval Mode</div>
            <select
              className='border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm'
              value={state.approvalMode}
              onChange={(event) =>
                setState((current) => ({
                  ...current,
                  approvalMode: event.target.value as StepFormState['approvalMode']
                }))
              }
            >
              {APPROVAL_MODES.map((mode) => (
                <option key={mode.value} value={mode.value}>
                  {mode.label}
                </option>
              ))}
            </select>
            <div className='text-muted-foreground text-xs'>
              {APPROVAL_MODES.find((mode) => mode.value === state.approvalMode)?.description}
            </div>
          </div>

          <div className='flex items-center justify-between rounded-lg border px-4 py-3'>
            <div>
              <div className='font-medium'>Required Step</div>
              <div className='text-muted-foreground text-sm'>
                Active workflows must keep at least one required step.
              </div>
            </div>
            <Switch
              checked={state.isRequired}
              onCheckedChange={(checked) => setState((current) => ({ ...current, isRequired: checked }))}
            />
          </div>

          <DialogFooter>
            <Button type='button' variant='outline' onClick={() => onOpenChange(false)}>
              Cancel
            </Button>
            <Button type='submit' isLoading={isPending}>
              {step ? 'Save Step' : 'Add Step'}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

function WorkflowCard({ workflowId }: { workflowId: string }) {
  const { data } = useSuspenseQuery(approvalWorkflowByIdOptions(workflowId));
  const workflow = data.workflow;
  const [workflowDialogOpen, setWorkflowDialogOpen] = React.useState(false);
  const [createStepOpen, setCreateStepOpen] = React.useState(false);
  const [editingStep, setEditingStep] = React.useState<ApprovalStepRecord | null>(null);

  const deleteMutation = useMutation({
    ...deleteApprovalWorkflowMutation,
    onSuccess: () => toast.success('Workflow deleted'),
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Delete failed')
  });
  const cloneMutation = useMutation({
    ...cloneApprovalWorkflowMutation,
    onSuccess: () => toast.success('Workflow cloned'),
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Clone failed')
  });
  const activateMutation = useMutation({
    ...activateApprovalWorkflowMutation,
    onSuccess: () => toast.success('Workflow activated'),
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Activate failed')
  });
  const deactivateMutation = useMutation({
    ...deactivateApprovalWorkflowMutation,
    onSuccess: () => toast.success('Workflow deactivated'),
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Deactivate failed')
  });
  const deleteStepMutation = useMutation({
    ...deleteApprovalWorkflowStepMutation,
    onSuccess: () => toast.success('Step deleted'),
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Delete step failed')
  });
  const reorderMutation = useMutation({
    ...reorderApprovalWorkflowStepsMutation,
    onSuccess: () => toast.success('Step order updated'),
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Reorder failed')
  });

  async function moveStep(stepId: string, direction: 'up' | 'down') {
    const index = workflow.steps.findIndex((step) => step.id === stepId);
    if (index < 0) return;
    const nextIndex = direction === 'up' ? index - 1 : index + 1;
    if (nextIndex < 0 || nextIndex >= workflow.steps.length) return;

    const reordered = [...workflow.steps];
    const [item] = reordered.splice(index, 1);
    reordered.splice(nextIndex, 0, item);

    await reorderMutation.mutateAsync({
      workflowId: workflow.id,
      values: {
        orderedStepIds: reordered.map((step) => step.id)
      }
    });
  }

  return (
    <div className='rounded-xl border p-5'>
      <div className='flex flex-wrap items-start justify-between gap-4'>
        <div className='space-y-2'>
          <div className='text-xl font-semibold'>{workflow.name}</div>
          <div className='text-muted-foreground text-sm'>
            {workflow.code} | {workflow.entityType}
          </div>
          {workflow.description ? (
            <div className='text-muted-foreground text-sm'>{workflow.description}</div>
          ) : null}
        </div>

        <div className='flex flex-wrap gap-2'>
          <Badge variant={workflow.isActive ? 'secondary' : 'outline'}>
            {workflow.isActive ? 'Active' : 'Inactive'}
          </Badge>
          <Badge variant='outline'>{workflow.steps.length} steps</Badge>
          {workflow.isSystem ? <Badge variant='outline'>System</Badge> : null}
          {workflow.usage.isLocked ? <Badge variant='destructive'>Locked</Badge> : null}
        </div>
      </div>

      <div className='mt-4 grid gap-3 md:grid-cols-3 xl:grid-cols-6'>
        <div className='rounded-lg border p-3'>
          <div className='text-muted-foreground text-xs'>Total Requests</div>
          <div className='text-lg font-semibold'>{workflow.usage.totalRequestCount}</div>
        </div>
        <div className='rounded-lg border p-3'>
          <div className='text-muted-foreground text-xs'>Pending Requests</div>
          <div className='text-lg font-semibold'>{workflow.usage.activeRequestCount}</div>
        </div>
        <div className='rounded-lg border p-3'>
          <div className='text-muted-foreground text-xs'>Active Matrices</div>
          <div className='text-lg font-semibold'>{workflow.usage.activeMatrixCount}</div>
        </div>
        <div className='rounded-lg border p-3 md:col-span-3 xl:col-span-3'>
          <div className='text-muted-foreground text-xs'>Safety</div>
          <div className='mt-1 text-sm'>
            {workflow.usage.lockedReason ?? 'This workflow is editable.'}
          </div>
        </div>
      </div>

      <div className='mt-4 flex flex-wrap gap-2'>
        <Button
          variant='outline'
          onClick={() => setWorkflowDialogOpen(true)}
          disabled={!workflow.usage.canEdit}
        >
          Edit Workflow
        </Button>
        <Button variant='outline' onClick={() => cloneMutation.mutate(workflow.id)} isLoading={cloneMutation.isPending}>
          Clone
        </Button>
        {workflow.isActive ? (
          <Button
            variant='outline'
            onClick={() => deactivateMutation.mutate(workflow.id)}
            isLoading={deactivateMutation.isPending}
            disabled={!workflow.usage.canDeactivate}
          >
            Deactivate
          </Button>
        ) : (
          <Button
            variant='outline'
            onClick={() => activateMutation.mutate(workflow.id)}
            isLoading={activateMutation.isPending}
          >
            Activate
          </Button>
        )}
        <Button
          variant='outline'
          onClick={() => deleteMutation.mutate(workflow.id)}
          isLoading={deleteMutation.isPending}
          disabled={!workflow.usage.canDelete}
        >
          Delete
        </Button>
        <Button
          onClick={() => setCreateStepOpen(true)}
          disabled={!workflow.usage.canEdit}
        >
          <Icons.add className='mr-2 h-4 w-4' />
          Add Step
        </Button>
      </div>

      <div className='mt-4 grid gap-3 md:grid-cols-2 xl:grid-cols-4'>
        {workflow.steps.map((step, index) => (
          <div key={step.id} className='rounded-lg border p-4'>
            <div className='flex items-start justify-between gap-2'>
              <div>
                <div className='font-medium'>Step {step.stepNumber}</div>
                <div className='text-muted-foreground mt-1 text-sm'>{step.roleName}</div>
              </div>
              <Badge variant={step.isRequired ? 'secondary' : 'outline'}>
                {step.isRequired ? 'Required' : 'Optional'}
              </Badge>
            </div>

            <div className='mt-3 flex flex-wrap gap-2'>
              <Badge variant='outline'>{step.roleCode}</Badge>
              <Badge variant='outline'>{step.approvalMode}</Badge>
            </div>

            {step.approvalMode !== 'sequential' ? (
              <div className='text-muted-foreground mt-3 text-xs'>
                Stored for future runtime support. Current engine still runs sequentially.
              </div>
            ) : null}

            <div className='mt-4 flex flex-wrap gap-2'>
              <Button
                size='sm'
                variant='outline'
                onClick={() => moveStep(step.id, 'up')}
                disabled={!workflow.usage.canEdit || index === 0 || reorderMutation.isPending}
              >
                Up
              </Button>
              <Button
                size='sm'
                variant='outline'
                onClick={() => moveStep(step.id, 'down')}
                disabled={
                  !workflow.usage.canEdit ||
                  index === workflow.steps.length - 1 ||
                  reorderMutation.isPending
                }
              >
                Down
              </Button>
              <Button
                size='sm'
                variant='outline'
                onClick={() => setEditingStep(step)}
                disabled={!workflow.usage.canEdit}
              >
                Edit
              </Button>
              <Button
                size='sm'
                variant='outline'
                onClick={() =>
                  deleteStepMutation.mutate({
                    workflowId: workflow.id,
                    stepId: step.id
                  })
                }
                isLoading={deleteStepMutation.isPending}
                disabled={!workflow.usage.canEdit}
              >
                Delete
              </Button>
            </div>
          </div>
        ))}
      </div>

      <WorkflowDialog
        open={workflowDialogOpen}
        onOpenChange={setWorkflowDialogOpen}
        workflow={workflow}
      />
      <StepDialog open={createStepOpen} onOpenChange={setCreateStepOpen} workflow={workflow} />
      <StepDialog
        open={editingStep !== null}
        onOpenChange={(open) => {
          if (!open) {
            setEditingStep(null);
          }
        }}
        workflow={workflow}
        step={editingStep ?? undefined}
      />
    </div>
  );
}

export function ApprovalWorkflowSettings() {
  const { data } = useSuspenseQuery(approvalWorkflowsQueryOptions());
  const [createOpen, setCreateOpen] = React.useState(false);

  return (
    <div className='space-y-6'>
      <div className='flex items-center justify-between gap-4 rounded-lg border p-4'>
        <div>
          <div className='font-medium'>Approval Workflow Builder</div>
          <div className='text-muted-foreground text-sm'>
            Configure approval workflows, clone locked flows, and manage ordered steps without touching seed code.
          </div>
        </div>
        <Button onClick={() => setCreateOpen(true)}>
          <Icons.add className='mr-2 h-4 w-4' />
          Create Workflow
        </Button>
      </div>

      {data.items.length === 0 ? (
        <div className='text-muted-foreground rounded-lg border border-dashed p-8 text-center text-sm'>
          No approval workflows configured yet.
        </div>
      ) : (
        <div className='space-y-4'>
          {data.items.map((workflow) => (
            <React.Suspense
              key={workflow.id}
              fallback={
                <div className='text-muted-foreground rounded-lg border p-5 text-sm'>
                  Loading workflow detail...
                </div>
              }
            >
              <WorkflowCard workflowId={workflow.id} />
            </React.Suspense>
          ))}
        </div>
      )}

      <WorkflowDialog open={createOpen} onOpenChange={setCreateOpen} />
    </div>
  );
}
