<template>
  <v-dialog :model-value="modelValue" max-width="640"
            @update:model-value="$emit('update:modelValue', $event)">
    <v-card>
      <v-card-title>{{ source ? 'Edit source' : 'Add subscription' }}</v-card-title>
      <v-card-text>
        <!-- Artist picker (only when adding without a pre-selected artist) -->
        <div v-if="!source && !initialArtist" class="mb-3">
          <v-combobox
            v-model="artistChoice"
            :items="artistMatches"
            item-title="name" item-value="id"
            label="Artist (type to search or create)"
            :loading="artistLoading"
            return-object hide-no-data
            @update:search="onArtistSearch"
          />
        </div>
        <div v-else-if="initialArtist && !source" class="text-caption mb-3">
          Adding source for <strong>{{ initialArtist.name }}</strong>
        </div>

        <v-select
          v-model="platform"
          :items="platformsItems"
          item-value="value"
          item-title="title"
          label="Platform"
        />
        <v-text-field v-model="url" label="URL" :error-messages="urlError" />
        <v-switch v-model="enabled" label="Enabled" color="accent" hide-details />

        <v-tabs v-model="configTab" class="mt-4">
          <v-tab value="structured">Structured</v-tab>
          <v-tab value="advanced">Advanced JSON</v-tab>
        </v-tabs>
        <v-window v-model="configTab" class="mt-2">
          <v-window-item value="structured">
            <v-switch
              v-model="structuredVideos"
              label="Include videos" color="accent" hide-details
            />
            <v-text-field
              v-model="structuredSince" label="Skip posts older than (YYYY-MM-DD)"
              placeholder="2024-01-01" hide-details class="mt-2"
            />
            <p class="text-caption mt-2" style="opacity: 0.75">
              More per-platform fields land here over time. Use Advanced JSON for everything else.
            </p>
          </v-window-item>
          <v-window-item value="advanced">
            <v-textarea
              v-model="jsonText" :error-messages="jsonError"
              label="config_overrides (JSON object)"
              auto-grow rows="6" spellcheck="false"
            />
          </v-window-item>
        </v-window>
      </v-card-text>
      <v-card-actions>
        <v-spacer />
        <v-btn variant="text" @click="$emit('update:modelValue', false)">Cancel</v-btn>
        <v-btn color="accent" variant="flat" :loading="busy" :disabled="!canSave" @click="save">
          Save
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import { useSourcesStore } from '../../stores/sources.js'
import { usePlatformsStore } from '../../stores/platforms.js'

const props = defineProps({
  modelValue: { type: Boolean, default: false },
  source: { type: Object, default: null },
  initialArtist: { type: Object, default: null },
})
const emit = defineEmits(['update:modelValue', 'saved'])
const store = useSourcesStore()
const platformsStore = usePlatformsStore()

const platformsItems = computed(() =>
  platformsStore.list.map(p => ({ value: p.key, title: p.name }))
)

const artistChoice = ref(null)
const artistMatches = ref([])
const artistLoading = ref(false)

const platform = ref('patreon')
const url = ref('')
const enabled = ref(true)
const urlError = ref('')

const configTab = ref('structured')
const structuredVideos = ref(true)
const structuredSince = ref('')
const jsonText = ref('{}')
const jsonError = ref('')

const busy = ref(false)

// Sync config_overrides between the two views.
const config = computed(() => {
  const out = {}
  if (!structuredVideos.value) out.videos = false
  if (structuredSince.value) out.since = structuredSince.value
  return out
})

watch([structuredVideos, structuredSince], () => {
  if (configTab.value === 'structured') {
    jsonText.value = JSON.stringify(config.value, null, 2)
    jsonError.value = ''
  }
})

watch(jsonText, (txt) => {
  if (configTab.value !== 'advanced') return
  try {
    const parsed = JSON.parse(txt || '{}')
    if (typeof parsed !== 'object' || Array.isArray(parsed) || parsed === null) {
      jsonError.value = 'Must be a JSON object'
      return
    }
    jsonError.value = ''
    // Reflect recognized keys into the structured view.
    structuredVideos.value = parsed.videos !== false
    structuredSince.value = parsed.since ?? ''
  } catch {
    jsonError.value = 'Invalid JSON'
  }
})

const canSave = computed(() => !jsonError.value && !!url.value.trim())

watch(() => props.modelValue, async (open) => {
  if (!open) return
  urlError.value = ''; jsonError.value = ''
  await platformsStore.loadAll()
  if (props.source) {
    platform.value = props.source.platform
    url.value = props.source.url
    enabled.value = props.source.enabled
    const co = props.source.config_overrides || {}
    structuredVideos.value = co.videos !== false
    structuredSince.value = co.since ?? ''
    jsonText.value = JSON.stringify(co, null, 2)
    artistChoice.value = { id: props.source.artist_id, name: props.source.artist_name }
  } else {
    platform.value = platformsStore.list[0]?.key || 'patreon'
    url.value = ''; enabled.value = true
    structuredVideos.value = true; structuredSince.value = ''
    jsonText.value = '{}'
    artistChoice.value = props.initialArtist
      ? { id: props.initialArtist.id, name: props.initialArtist.name }
      : null
  }
})

async function onArtistSearch(q) {
  if (!q || (typeof q !== 'string')) return
  artistLoading.value = true
  try {
    artistMatches.value = await store.autocompleteArtist(q)
  } finally {
    artistLoading.value = false
  }
}

function _parseConfig() {
  if (configTab.value === 'structured') return Object.keys(config.value).length ? config.value : null
  const parsed = JSON.parse(jsonText.value || '{}')
  return Object.keys(parsed).length ? parsed : null
}

async function save() {
  urlError.value = ''
  if (!url.value.trim()) { urlError.value = 'URL is required'; return }
  let configOut
  try { configOut = _parseConfig() } catch { jsonError.value = 'Invalid JSON'; return }

  busy.value = true
  try {
    if (props.source) {
      await store.update(props.source.id, {
        platform: platform.value, url: url.value.trim(),
        enabled: enabled.value, config_overrides: configOut,
      }, props.source.artist_id)
    } else {
      let artistId
      if (props.initialArtist) artistId = props.initialArtist.id
      else if (artistChoice.value && typeof artistChoice.value === 'object') artistId = artistChoice.value.id
      else if (typeof artistChoice.value === 'string') {
        const { artist } = await store.findOrCreateArtist(artistChoice.value)
        artistId = artist.id
      } else {
        urlError.value = 'Pick or create an artist first'; busy.value = false; return
      }
      await store.create({
        artist_id: artistId, platform: platform.value, url: url.value.trim(),
        enabled: enabled.value, config_overrides: configOut,
      })
    }
    emit('saved')
  } catch (e) {
    if (e?.body?.error === 'duplicate') {
      urlError.value = `Duplicate (existing source id ${e.body.existing_id})`
    } else {
      urlError.value = String(e?.detail || e?.message || e)
    }
  } finally {
    busy.value = false
  }
}
</script>
