<script setup lang="ts">
import { ref, computed } from 'vue'
import { useForm } from 'vee-validate'
import { toTypedSchema } from '@vee-validate/zod'
import * as z from 'zod'
import { useAuth } from '@/composables/useAuthService'
import { useToast } from '@/core/composables/useToast'
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
import type { ExpensesAPI } from '../../services/ExpensesAPI'
import type { Account } from '../../types'
import { PermissionType } from '../../types'

import { Button } from '@/components/ui/button'
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import {
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Textarea } from '@/components/ui/textarea'
import { Loader2 } from 'lucide-vue-next'

interface Props {
  isOpen: boolean
  accounts: Account[]
}

const props = defineProps<Props>()

const emit = defineEmits<{
  close: []
  permissionGranted: []
}>()

const { user } = useAuth()
const toast = useToast()
const expensesAPI = injectService<ExpensesAPI>(SERVICE_TOKENS.EXPENSES_API)

const isGranting = ref(false)

const adminKey = computed(() => user.value?.wallets?.[0]?.adminkey)

// Form schema
const formSchema = toTypedSchema(
  z.object({
    user_id: z.string().min(1, 'User ID is required'),
    account_id: z.string().min(1, 'Account is required'),
    permission_type: z.nativeEnum(PermissionType, {
      errorMap: () => ({ message: 'Permission type is required' })
    }),
    notes: z.string().optional(),
    expires_at: z.string().optional()
  })
)

// Setup form
const form = useForm({
  validationSchema: formSchema,
  initialValues: {
    user_id: '',
    account_id: '',
    permission_type: PermissionType.READ,
    notes: '',
    expires_at: ''
  }
})

const { resetForm, meta } = form
const isFormValid = computed(() => meta.value.valid)

// Permission type options
const permissionTypes = [
  { value: PermissionType.READ, label: 'Read', description: 'View account and balance' },
  {
    value: PermissionType.SUBMIT_EXPENSE,
    label: 'Submit Expense',
    description: 'Submit expenses to this account'
  },
  { value: PermissionType.MANAGE, label: 'Manage', description: 'Full account management' }
]

// Submit form
const onSubmit = form.handleSubmit(async (values) => {
  if (!adminKey.value) {
    toast.error('Admin access required')
    return
  }

  isGranting.value = true

  try {
    await expensesAPI.grantPermission(adminKey.value, {
      user_id: values.user_id,
      account_id: values.account_id,
      permission_type: values.permission_type,
      notes: values.notes || undefined,
      expires_at: values.expires_at || undefined
    })

    emit('permissionGranted')
    resetForm()
  } catch (error) {
    console.error('Failed to grant permission:', error)
    toast.error('Failed to grant permission', {
      description: error instanceof Error ? error.message : 'Unknown error'
    })
  } finally {
    isGranting.value = false
  }
})

// Handle dialog close
function handleClose() {
  if (!isGranting.value) {
    resetForm()
    emit('close')
  }
}
</script>

<template>
  <Dialog :open="props.isOpen" @update:open="handleClose">
    <DialogContent class="sm:max-w-[500px]">
      <DialogHeader>
        <DialogTitle>Grant Account Permission</DialogTitle>
        <DialogDescription>
          Grant a user permission to access an expense account. Permissions on parent accounts
          cascade to children.
        </DialogDescription>
      </DialogHeader>

      <form @submit="onSubmit" class="space-y-4">
        <!-- User ID -->
        <FormField v-slot="{ componentField }" name="user_id">
          <FormItem>
            <FormLabel>User ID *</FormLabel>
            <FormControl>
              <Input
                placeholder="Enter user wallet ID"
                v-bind="componentField"
                :disabled="isGranting"
              />
            </FormControl>
            <FormDescription>The wallet ID of the user to grant permission to</FormDescription>
            <FormMessage />
          </FormItem>
        </FormField>

        <!-- Account -->
        <FormField v-slot="{ componentField }" name="account_id">
          <FormItem>
            <FormLabel>Account *</FormLabel>
            <Select v-bind="componentField" :disabled="isGranting">
              <FormControl>
                <SelectTrigger>
                  <SelectValue placeholder="Select account" />
                </SelectTrigger>
              </FormControl>
              <SelectContent>
                <SelectItem
                  v-for="account in props.accounts"
                  :key="account.id"
                  :value="account.id"
                >
                  {{ account.name }}
                </SelectItem>
              </SelectContent>
            </Select>
            <FormDescription>Account to grant access to</FormDescription>
            <FormMessage />
          </FormItem>
        </FormField>

        <!-- Permission Type -->
        <FormField v-slot="{ componentField }" name="permission_type">
          <FormItem>
            <FormLabel>Permission Type *</FormLabel>
            <Select v-bind="componentField" :disabled="isGranting">
              <FormControl>
                <SelectTrigger>
                  <SelectValue placeholder="Select permission type" />
                </SelectTrigger>
              </FormControl>
              <SelectContent>
                <SelectItem
                  v-for="type in permissionTypes"
                  :key="type.value"
                  :value="type.value"
                >
                  <div>
                    <div class="font-medium">{{ type.label }}</div>
                    <div class="text-sm text-muted-foreground">{{ type.description }}</div>
                  </div>
                </SelectItem>
              </SelectContent>
            </Select>
            <FormDescription>Type of permission to grant</FormDescription>
            <FormMessage />
          </FormItem>
        </FormField>

        <!-- Expiration Date (Optional) -->
        <FormField v-slot="{ componentField }" name="expires_at">
          <FormItem>
            <FormLabel>Expiration Date (Optional)</FormLabel>
            <FormControl>
              <Input
                type="datetime-local"
                v-bind="componentField"
                :disabled="isGranting"
              />
            </FormControl>
            <FormDescription>Leave empty for permanent access</FormDescription>
            <FormMessage />
          </FormItem>
        </FormField>

        <!-- Notes (Optional) -->
        <FormField v-slot="{ componentField }" name="notes">
          <FormItem>
            <FormLabel>Notes (Optional)</FormLabel>
            <FormControl>
              <Textarea
                placeholder="Add notes about this permission..."
                v-bind="componentField"
                :disabled="isGranting"
              />
            </FormControl>
            <FormDescription>Optional notes for admin reference</FormDescription>
            <FormMessage />
          </FormItem>
        </FormField>

        <DialogFooter>
          <Button
            type="button"
            variant="outline"
            @click="handleClose"
            :disabled="isGranting"
          >
            Cancel
          </Button>
          <Button type="submit" :disabled="isGranting || !isFormValid">
            <Loader2 v-if="isGranting" class="mr-2 h-4 w-4 animate-spin" />
            {{ isGranting ? 'Granting...' : 'Grant Permission' }}
          </Button>
        </DialogFooter>
      </form>
    </DialogContent>
  </Dialog>
</template>
