<script setup lang="ts">
import { ref, shallowRef, computed, watch } from 'vue'
import { useServicesStore } from '@MailManager/stores/servicesStore'
import { useProvidersStore } from '@MailManager/stores/providersStore'
import type { ProviderObject, ServiceObject } from '@MailManager/models'
import ProviderAuxiliaryPanel from '@MailManager/components/steps/ProviderAuxiliaryPanel.vue'
import ProviderProtocolPanel from '@MailManager/components/steps/ProviderProtocolPanel.vue'
import ProviderAuthPanel from '@MailManager/components/steps/ProviderAuthPanel.vue'
import TestAndSavePanel from '@MailManager/components/steps/TestAndSavePanel.vue'

type EditTab = 'general' | 'auxiliary' | 'protocol' | 'auth'

const props = defineProps<{
  modelValue: boolean
  serviceProvider: string
  serviceIdentifier: string | number
  user?: string
}>()

const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  'saved': []
}>()

const servicesStore = useServicesStore()
const providersStore = useProvidersStore()

const dialogOpen = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

const currentTab = ref<EditTab>('general')
const saving = ref(false)
const loading = ref(false)
const loadError = ref<string | null>(null)

const localProvider = shallowRef<ProviderObject | null>(null)
const localService = shallowRef<ServiceObject | null>(null)

// Validation states
const testAndSaveValid = ref(false)

function serviceRequiresConnectionTest(service: ServiceObject | null): boolean {
  return !!(service?.location?.mutated() || service?.identity?.mutated())
}

const tabItems = [
  {
    title: 'General',
    icon: 'mdi-view-dashboard-outline',
    value: 'general' as const
  },
  {
    title: 'Auxiliary Settings',
    icon: 'mdi-tune-variant',
    value: 'auxiliary' as const
  },
  {
    title: 'Protocol',
    icon: 'mdi-tune-vertical',
    value: 'protocol' as const
  },
  {
    title: 'Authentication',
    icon: 'mdi-shield-key-outline',
    value: 'auth' as const
  }
]

const canSave = computed(() => {
  return !serviceRequiresConnectionTest(localService.value) || testAndSaveValid.value
})

const showSaveButton = computed(() => currentTab.value === 'general')
const accountReady = computed(() => localProvider.value !== null && localService.value !== null)

// Load service data when the dialog is open and the target account is available.
watch(
  () => [props.modelValue, props.serviceProvider, props.serviceIdentifier] as const,
  async ([isOpen, serviceProvider, serviceIdentifier]) => {
    if (!isOpen || !serviceProvider || !serviceIdentifier) {
      return
    }

    await load()
  },
  { immediate: true }
)

async function load() {
  loading.value = true
  loadError.value = null
  localProvider.value = null
  localService.value = null

  if (!props.serviceProvider || !props.serviceIdentifier) {
    console.error('[Mail Manager][Edit Account Dialog] - Cannot open dialog missing service or provider identifier')
    loadError.value = 'missing service or provider identifier'
    loading.value = false
    return
  }

  try {
    const [provider, service] = await Promise.all([
      providersStore.provider(props.serviceProvider) ?? providersStore.fetch(props.serviceProvider),
      // acting-user context always fetches fresh, bypassing the shared cache
      props.user
        ? servicesStore.fetch(props.serviceProvider, props.serviceIdentifier, props.user)
        : servicesStore.service(props.serviceProvider, props.serviceIdentifier) ?? servicesStore.fetch(props.serviceProvider, props.serviceIdentifier)
    ])

    localProvider.value = provider.clone()
    localService.value = service.clone()
  } catch (error) {
    console.error('[Mail Manager][Edit Account Dialog] - Failed to load service:', error)
    loadError.value = 'Failed to load service details'
  } finally {
    loading.value = false
  }
}

function close() {
  dialogOpen.value = false
  // Reset state after animation
  setTimeout(resetForm, 300)
}

function resetForm() {
  currentTab.value = 'general'
  localService.value = null
  localProvider.value = null
  loadError.value = null
}

function isTabDisabled(tab: EditTab) {
  if (tab === 'auth') {
    return !localService.value?.location
  }

  return false
}

function handleUpdate(mutatedService: ServiceObject) {
  localService.value = mutatedService

  if (serviceRequiresConnectionTest(mutatedService)) {
    testAndSaveValid.value = false
  }
}

async function testConnection() {
  try {
    if (!localService.value) {
      return {
        success: false,
        message: 'Missing service configuration'
      }
    }

    let testResult = null
    
    if (serviceRequiresConnectionTest(localService.value)) {
      testResult = await servicesStore.test(
        localService.value.provider,
        null,
        localService.value.location,
        localService.value.identity,
        props.user
      )
    } else {
      testResult = await servicesStore.test(
        localService.value.provider,
        localService.value.identifier,
        undefined,
        undefined,
        props.user
      )
    }

    testAndSaveValid.value = testResult.success
    return testResult
  } catch (error) {
    console.error('[Mail Manager][Edit Account Dialog] - Test connection failed:', error)
    return {
      success: false,
      message: 'Test failed due to an unexpected error'
    }
  }
}

async function saveAccount() {
  if (!localService.value) {
    console.error('[Mail Manager][Edit Account Dialog] - No service data to save')
    return
  }
  // No changes made, just close the dialog
  if (!localService.value.mutated() && !localService.value.location?.mutated() && !localService.value.identity?.mutated()) {
    close()
    return
  }

  saving.value = true

  try {
    await servicesStore.update(
      localService.value.provider,
      localService.value.identifier as string | number,
      true, // delta update
      localService.value,
      props.user
    )

    emit('saved')
    close()
  } catch (error) {
    console.error('[Mail Manager][Edit Account Dialog] - Failed to save service:', error)
    // TODO: Show error message to user
  } finally {
    saving.value = false
  }
}
</script>

<template>
  <v-dialog
    v-model="dialogOpen"
    max-width="900"
    persistent
    scrollable
  >
    <v-card>
      <v-card-title class="d-flex justify-space-between align-center pa-6">
        <span class="text-h5">Edit Mail Account</span>
        <v-btn
          icon="mdi-close"
          variant="text"
          @click="close"
        />
      </v-card-title>

      <v-divider />

      <v-card-text v-if="loading || (!loadError && !accountReady)" class="text-center py-8">
        <v-progress-circular indeterminate color="primary" />
        <p class="text-caption text-medium-emphasis mt-2">Loading account...</p>
      </v-card-text>

      <v-card-text v-else-if="loadError" class="pa-6">
        <v-alert type="error" variant="tonal">
          {{ loadError }}
        </v-alert>
      </v-card-text>

      <v-card-text v-else class="pa-0">
        <v-tabs
          v-model="currentTab"
          bg-color="transparent"
          grow
          class="px-4 pt-2"
        >
          <v-tab
            v-for="item in tabItems"
            :key="item.value"
            :value="item.value"
            :disabled="isTabDisabled(item.value)"
          >
            <v-icon start>{{ item.icon }}</v-icon>
            {{ item.title }}
          </v-tab>
        </v-tabs>

        <v-divider />

        <v-window v-model="currentTab">
          <v-window-item value="general">
            <v-card flat class="pa-6">
              <TestAndSavePanel
                v-if="localProvider && localService"
                :provider="localProvider!"
                :service="localService!"
                :on-test="testConnection"
                @update:service="handleUpdate"
              />
            </v-card>
          </v-window-item>

          <v-window-item value="auxiliary">
            <v-card flat class="pa-6">
              <ProviderAuxiliaryPanel
                v-if="localProvider && localService"
                :provider="localProvider!"
                :service="localService!"
                @update:service="handleUpdate"
              />
            </v-card>
          </v-window-item>

          <v-window-item value="protocol">
            <v-card flat class="pa-6">
              <ProviderProtocolPanel
                v-if="localProvider && localService"
                :provider="localProvider!"
                :service="localService!"
                @update:service="handleUpdate"
              />
            </v-card>
          </v-window-item>

          <v-window-item value="auth">
            <v-card flat class="pa-6">
              <ProviderAuthPanel
                v-if="localProvider && localService"
                :provider="localProvider!"
                :service="localService!"
                @update:service="handleUpdate"
              />
            </v-card>
          </v-window-item>
        </v-window>
      </v-card-text>

      <v-divider />

      <v-card-actions class="pa-6">
        <v-spacer />
        
        <v-btn
          variant="text"
          @click="close"
        >
          Cancel
        </v-btn>

        <!-- Save Button -->
        <v-btn
          v-if="showSaveButton"
          color="primary"
          :loading="saving"
          :disabled="!canSave"
          @click="saveAccount"
        >
          <v-icon start>mdi-content-save</v-icon>
          Save Changes
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>
