<template>
  <Dialog :open="open" @update:open="$emit('update:open', $event)">
    <DialogContent class="sm:max-w-2xl max-h-[85vh] flex flex-col">
      <DialogHeader>
        <DialogTitle>{{ role ? 'Edit Role' : 'Create Role' }}</DialogTitle>
        <DialogDescription>
          {{ role?.is_system
            ? 'System role permissions are editable, but the name and description cannot be changed.'
            : 'Define a role and the permissions it grants.' }}
        </DialogDescription>
      </DialogHeader>

      <form @submit.prevent="handleSubmit" class="flex-1 min-h-0 flex flex-col gap-4">
        <div class="grid grid-cols-2 gap-4 flex-shrink-0">
          <div class="space-y-2">
            <Label for="role_name">Name</Label>
            <Input
              id="role_name"
              v-model="formData.name"
              placeholder="e.g. Reviewer"
              required
              :disabled="role?.is_system"
            />
          </div>
          <div class="space-y-2">
            <Label for="role_description">Description</Label>
            <Input
              id="role_description"
              v-model="formData.description"
              placeholder="What this role is for"
              :disabled="role?.is_system"
            />
          </div>
        </div>

        <div class="flex-1 min-h-0 flex flex-col gap-2">
          <div class="flex items-center justify-between flex-shrink-0">
            <Label>Permissions</Label>
            <span class="text-xs text-muted-foreground">{{ selectedPermissionIds.size }} of {{ permissions.length }} selected</span>
          </div>

          <div class="flex-1 min-h-0 overflow-y-auto rounded-md border p-3 space-y-4">
            <div v-for="group in permissionGroups" :key="group.title" class="space-y-2">
              <h4 class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">{{ group.title }}</h4>
              <div class="space-y-2">
                <div v-for="resource in group.resources" :key="resource" class="rounded-md border bg-muted/30 p-2.5">
                  <div class="flex items-center justify-between mb-2">
                    <div class="flex items-center gap-2 text-sm font-medium capitalize">
                      <component :is="resourceIcon(resource)" class="h-4 w-4 text-muted-foreground" />
                      {{ resource }}
                    </div>
                    <button
                      type="button"
                      class="text-xs text-muted-foreground hover:text-foreground hover:underline"
                      @click="toggleAllForResource(resource)"
                    >
                      {{ allSelectedForResource(resource) ? 'Clear' : 'Select all' }}
                    </button>
                  </div>
                  <div class="flex flex-wrap gap-x-4 gap-y-1.5">
                    <label
                      v-for="perm in permissionsForResource(resource)"
                      :key="perm.id"
                      class="flex items-center gap-1.5 text-sm cursor-pointer"
                      :title="perm.description || undefined"
                    >
                      <Checkbox
                        :model-value="selectedPermissionIds.has(perm.id)"
                        @update:model-value="(val) => togglePermission(perm.id, !!val)"
                      />
                      {{ actionLabel(perm.action) }}
                    </label>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <p v-if="formError" class="text-sm text-destructive flex-shrink-0">{{ formError }}</p>

        <DialogFooter class="flex-shrink-0">
          <Button type="button" variant="outline" @click="$emit('update:open', false)">Cancel</Button>
          <Button type="submit" :disabled="saving">{{ saving ? 'Saving...' : 'Save' }}</Button>
        </DialogFooter>
      </form>
    </DialogContent>
  </Dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import {
  Package, Camera, ListTodo, UserCheck, CheckCircle2, UploadCloud, Paperclip, MessageSquare, Shield
} from 'lucide-vue-next'
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter
} from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Checkbox } from '@/components/ui/checkbox'
import type { Role, Permission } from '@/services/role'

interface Props {
  open: boolean
  role: Role | null
  permissions: Permission[]
  saving?: boolean
}

const props = defineProps<Props>()
const emit = defineEmits<{
  'update:open': [value: boolean]
  saved: [data: { name?: string; description?: string; permission_ids: number[] }]
}>()

const formData = ref({ name: '', description: '' })
const selectedPermissionIds = ref<Set<number>>(new Set())
const formError = ref('')

// Resources grouped into scannable sections, in a fixed, deliberate order
// (not alphabetical) so related concepts sit together.
const RESOURCE_GROUPS: { title: string; resources: string[] }[] = [
  { title: 'Production', resources: ['asset', 'shot', 'task'] },
  { title: 'Task workflow', resources: ['assignment', 'submission', 'upload'] },
  { title: 'Review', resources: ['review'] },
  { title: 'Notes', resources: ['note'] },
]

const RESOURCE_ICONS: Record<string, any> = {
  asset: Package,
  shot: Camera,
  task: ListTodo,
  assignment: UserCheck,
  submission: UploadCloud,
  upload: Paperclip,
  review: CheckCircle2,
  note: MessageSquare,
}

const ACTION_LABELS: Record<string, string> = {
  create: 'Create',
  edit: 'Edit',
  delete: 'Delete',
  publish: 'Approve',
  retake: 'Request Retake',
  view_internal: 'View Internal',
  view_client: 'View Client',
  change_status: 'Change Status',
  edit_self: 'Edit Own',
  delete_self: 'Delete Own',
  edit_other: "Edit Others'",
  delete_other: "Delete Others'",
}

function resourceIcon(resource: string) {
  return RESOURCE_ICONS[resource] ?? Shield
}

function actionLabel(action: string): string {
  return ACTION_LABELS[action] ?? action
}

// Only show groups/resources that actually have permissions in the catalog,
// and fall back to a catch-all group for any future resource not yet
// assigned to a section above (so nothing silently disappears from the UI).
const permissionGroups = computed(() => {
  const knownResources = new Set(RESOURCE_GROUPS.flatMap(g => g.resources))
  const groups = RESOURCE_GROUPS
    .map(g => ({ title: g.title, resources: g.resources.filter(r => permissionsForResource(r).length > 0) }))
    .filter(g => g.resources.length > 0)

  const otherResources = [...new Set(props.permissions.map(p => p.resource))].filter(r => !knownResources.has(r))
  if (otherResources.length > 0) {
    groups.push({ title: 'Other', resources: otherResources })
  }
  return groups
})

function permissionsForResource(resource: string): Permission[] {
  return props.permissions.filter(p => p.resource === resource)
}

function allSelectedForResource(resource: string): boolean {
  const perms = permissionsForResource(resource)
  return perms.length > 0 && perms.every(p => selectedPermissionIds.value.has(p.id))
}

function toggleAllForResource(resource: string) {
  const perms = permissionsForResource(resource)
  const shouldSelect = !allSelectedForResource(resource)
  for (const perm of perms) {
    if (shouldSelect) selectedPermissionIds.value.add(perm.id)
    else selectedPermissionIds.value.delete(perm.id)
  }
}

function togglePermission(id: number, checked: boolean) {
  if (checked) selectedPermissionIds.value.add(id)
  else selectedPermissionIds.value.delete(id)
}

watch(() => props.open, (isOpen) => {
  if (!isOpen) return
  formError.value = ''
  formData.value = {
    name: props.role?.name ?? '',
    description: props.role?.description ?? ''
  }
  selectedPermissionIds.value = new Set(props.role?.permissions.map(p => p.id) ?? [])
})

function handleSubmit() {
  formError.value = ''
  if (!props.role && !formData.value.name.trim()) {
    formError.value = 'Name is required'
    return
  }

  const payload = props.role?.is_system
    ? { permission_ids: [...selectedPermissionIds.value] }
    : {
        name: formData.value.name,
        description: formData.value.description || undefined,
        permission_ids: [...selectedPermissionIds.value]
      }
  emit('saved', payload)
}
</script>
