'use client';

import * as React from 'react';
import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
import { toast } from 'sonner';
import { BUSINESS_ROLES, PERMISSIONS } from '@/lib/auth/rbac';
import { Icons } from '@/components/icons';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Switch } from '@/components/ui/switch';
import { approvalWorkflowsQueryOptions } from '@/features/foundation/approval/queries';
import {
  createApprovalEscalationPolicyMutation,
  deleteApprovalEscalationPolicyMutation,
  updateApprovalEscalationPolicyMutation
} from '../api/mutations';
import { approvalEscalationPoliciesOptions } from '../api/queries';
import type { EscalationPolicyItem, EscalationPolicyPayload } from '../api/types';

type EscalationFormState = {
  workflowId: string;
  stepNumber: string;
  triggerAfterHours: string;
  targetType: EscalationPolicyPayload['targetType'];
  targetValue: string;
  isActive: boolean;
};

function toEscalationState(policy?: EscalationPolicyItem): EscalationFormState {
  return {
    workflowId: policy?.workflowId ?? '',
    stepNumber: String(policy?.stepNumber ?? 1),
    triggerAfterHours: String(policy?.triggerAfterHours ?? 24),
    targetType: policy?.targetType ?? 'manager',
    targetValue: policy?.targetValue ?? '',
    isActive: policy?.isActive ?? true
  };
}

function EscalationPolicyDialog({
  open,
  onOpenChange,
  policy
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  policy?: EscalationPolicyItem;
}) {
  const workflowsQuery = useSuspenseQuery(approvalWorkflowsQueryOptions());
  const [state, setState] = React.useState<EscalationFormState>(toEscalationState(policy));
  const createMutation = useMutation({
    ...createApprovalEscalationPolicyMutation,
    onSuccess: () => {
      toast.success('Escalation policy created');
      onOpenChange(false);
    },
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Create failed')
  });
  const updateMutation = useMutation({
    ...updateApprovalEscalationPolicyMutation,
    onSuccess: () => {
      toast.success('Escalation policy updated');
      onOpenChange(false);
    },
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Update failed')
  });

  React.useEffect(() => {
    if (open) {
      const workflowId = policy?.workflowId ?? workflowsQuery.data.items[0]?.id ?? '';
      setState({ ...toEscalationState(policy), workflowId });
    }
  }, [open, policy, workflowsQuery.data.items]);

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

  async function onSubmit(event: React.FormEvent) {
    event.preventDefault();
    const payload: EscalationPolicyPayload = {
      workflowId: state.workflowId,
      stepNumber: Number(state.stepNumber),
      triggerAfterHours: Number(state.triggerAfterHours),
      targetType: state.targetType,
      targetValue: state.targetValue.trim() || null,
      isActive: state.isActive
    };

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

    await createMutation.mutateAsync(payload);
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className='sm:max-w-2xl'>
        <DialogHeader>
          <DialogTitle>{policy ? 'Edit Escalation Policy' : 'Create Escalation Policy'}</DialogTitle>
        </DialogHeader>
        <form className='space-y-4' onSubmit={onSubmit}>
          <div className='grid gap-4 md:grid-cols-2'>
            <div className='space-y-2'>
              <div className='text-sm font-medium'>Workflow</div>
              <select
                className='border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm'
                value={state.workflowId}
                onChange={(event) =>
                  setState((current) => ({ ...current, workflowId: event.target.value }))
                }
              >
                {workflowsQuery.data.items.map((workflow) => (
                  <option key={workflow.id} value={workflow.id}>
                    {workflow.name}
                  </option>
                ))}
              </select>
            </div>
            <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>
          </div>
          <div className='grid gap-4 md:grid-cols-2'>
            <div className='space-y-2'>
              <div className='text-sm font-medium'>Trigger After Hours</div>
              <Input
                type='number'
                min={1}
                value={state.triggerAfterHours}
                onChange={(event) =>
                  setState((current) => ({
                    ...current,
                    triggerAfterHours: event.target.value
                  }))
                }
              />
            </div>
            <div className='space-y-2'>
              <div className='text-sm font-medium'>Target Type</div>
              <select
                className='border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm'
                value={state.targetType}
                onChange={(event) =>
                  setState((current) => ({
                    ...current,
                    targetType: event.target.value as EscalationFormState['targetType']
                  }))
                }
              >
                <option value='manager'>Manager</option>
                <option value='requester'>Requester</option>
                <option value='explicit_user'>Explicit User</option>
                <option value='role'>Role</option>
                <option value='permission_group'>Permission Group</option>
              </select>
            </div>
          </div>
          <div className='space-y-2'>
            <div className='text-sm font-medium'>Target Value</div>
            {state.targetType === 'role' ? (
              <select
                className='border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm'
                value={state.targetValue}
                onChange={(event) =>
                  setState((current) => ({ ...current, targetValue: event.target.value }))
                }
              >
                <option value=''>Select role</option>
                {BUSINESS_ROLES.map((role) => (
                  <option key={role} value={role}>
                    {role}
                  </option>
                ))}
              </select>
            ) : state.targetType === 'permission_group' ? (
              <select
                className='border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm'
                value={state.targetValue}
                onChange={(event) =>
                  setState((current) => ({ ...current, targetValue: event.target.value }))
                }
              >
                <option value=''>Select permission</option>
                {Object.values(PERMISSIONS).map((permission) => (
                  <option key={permission} value={permission}>
                    {permission}
                  </option>
                ))}
              </select>
            ) : (
              <Input
                value={state.targetValue}
                onChange={(event) =>
                  setState((current) => ({ ...current, targetValue: event.target.value }))
                }
                placeholder={
                  state.targetType === 'manager'
                    ? 'Optional role code, otherwise organization admins'
                    : state.targetType === 'explicit_user'
                      ? 'User id'
                      : 'Optional'
                }
              />
            )}
          </div>
          <div className='flex items-center justify-between rounded-lg border px-4 py-3'>
            <div>
              <div className='font-medium'>Active Policy</div>
              <div className='text-muted-foreground text-sm'>
                Inactive escalation policies are ignored by the scheduler.
              </div>
            </div>
            <Switch
              checked={state.isActive}
              onCheckedChange={(checked) =>
                setState((current) => ({ ...current, isActive: checked }))
              }
            />
          </div>
          <DialogFooter>
            <Button type='button' variant='outline' onClick={() => onOpenChange(false)}>
              Cancel
            </Button>
            <Button type='submit' isLoading={isPending}>
              {policy ? 'Save Policy' : 'Create Policy'}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

export function EscalationPolicySettings() {
  const escalationPoliciesQuery = useSuspenseQuery(approvalEscalationPoliciesOptions());
  const [createOpen, setCreateOpen] = React.useState(false);
  const [editingPolicy, setEditingPolicy] = React.useState<EscalationPolicyItem | null>(null);
  const deleteMutation = useMutation({
    ...deleteApprovalEscalationPolicyMutation,
    onSuccess: () => toast.success('Escalation policy deleted'),
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Delete failed')
  });

  return (
    <div className='space-y-6'>
      <div className='flex items-center justify-between rounded-lg border p-4'>
        <div>
          <div className='font-medium'>Approval Escalation Policies</div>
          <div className='text-muted-foreground text-sm'>
            Define who gets notified when a pending step waits too long.
          </div>
        </div>
        <Button onClick={() => setCreateOpen(true)}>
          <Icons.add className='mr-2 h-4 w-4' />
          Create Policy
        </Button>
      </div>

      <div className='space-y-4'>
        {escalationPoliciesQuery.data.items.map((policy) => (
          <div key={policy.id} className='rounded-lg border p-4'>
            <div className='flex items-start justify-between gap-4'>
              <div>
                <div className='font-medium'>
                  {policy.workflowName} | Step {policy.stepNumber}
                </div>
                <div className='text-muted-foreground mt-1 text-sm'>
                  Escalate after {policy.triggerAfterHours} hours to {policy.targetType}
                  {policy.targetValue ? `: ${policy.targetValue}` : ''}
                </div>
                <div className='mt-3 flex flex-wrap gap-2'>
                  <Badge variant='outline'>{policy.targetType}</Badge>
                  <Badge variant='outline'>{policy.triggerAfterHours}h</Badge>
                  <Badge variant={policy.isActive ? 'secondary' : 'outline'}>
                    {policy.isActive ? 'Active' : 'Inactive'}
                  </Badge>
                </div>
              </div>
              <div className='flex gap-2'>
                <Button size='sm' variant='outline' onClick={() => setEditingPolicy(policy)}>
                  Edit
                </Button>
                <Button
                  size='sm'
                  variant='outline'
                  onClick={() => deleteMutation.mutate(policy.id)}
                  isLoading={deleteMutation.isPending}
                >
                  Delete
                </Button>
              </div>
            </div>
          </div>
        ))}
        {escalationPoliciesQuery.data.items.length === 0 ? (
          <div className='text-muted-foreground rounded-lg border border-dashed p-8 text-center text-sm'>
            No escalation policies configured yet.
          </div>
        ) : null}
      </div>

      <EscalationPolicyDialog open={createOpen} onOpenChange={setCreateOpen} />
      <EscalationPolicyDialog
        open={editingPolicy !== null}
        onOpenChange={(open) => {
          if (!open) {
            setEditingPolicy(null);
          }
        }}
        policy={editingPolicy ?? undefined}
      />
    </div>
  );
}
