<template>
	<div class="content csv-migration">
		<h1>{{ $t('migrate.titleService', {name: 'CSV'}) }}</h1>
		<p>{{ $t('migrate.csv.description') }}</p>

		<Message
			v-if="error"
			variant="danger"
			class="mbe-4"
		>
			{{ error }}
		</Message>

		<!-- Step 1: File Upload -->
		<div
			v-if="step === 'upload'"
			class="upload-step"
		>
			<p>{{ $t('migrate.csv.uploadDescription') }}</p>
			<input
				ref="uploadInput"
				class="is-hidden"
				type="file"
				accept=".csv,.txt"
				@change="handleFileUpload"
			>
			<XButton
				:loading="isLoading"
				:disabled="isLoading || undefined"
				@click="uploadInput?.click()"
			>
				{{ $t('migrate.csv.selectFile') }}
			</XButton>
		</div>

		<!-- Step 2: Column Mapping -->
		<div
			v-else-if="step === 'mapping'"
			class="mapping-step"
		>
			<div class="mapping-header">
				<p>{{ $t('migrate.csv.columnMappingDescription') }}</p>
			</div>

			<!-- Parsing Options -->
			<div class="parsing-options card">
				<h3>{{ $t('migrate.csv.parsingOptions') }}</h3>
				<div class="options-grid">
					<div class="option-group">
						<label for="delimiter">{{ $t('migrate.csv.delimiter') }}</label>
						<div class="select is-fullwidth">
							<select
								id="delimiter"
								v-model="config.delimiter"
								@change="updatePreview"
							>
								<option
									v-for="delim in SUPPORTED_DELIMITERS"
									:key="delim"
									:value="delim"
								>
									{{ getDelimiterLabel(delim) }}
								</option>
							</select>
						</div>
					</div>
					<div class="option-group">
						<label for="dateFormat">{{ $t('migrate.csv.dateFormat') }}</label>
						<div class="select is-fullwidth">
							<select
								id="dateFormat"
								v-model="config.date_format"
								@change="updatePreview"
							>
								<option
									v-for="format in SUPPORTED_DATE_FORMATS"
									:key="format"
									:value="format"
								>
									{{ getDateFormatLabel(format) }}
								</option>
							</select>
						</div>
					</div>
					<div class="option-group">
						<label for="skipRows">{{ $t('migrate.csv.skipRows') }}</label>
						<input
							id="skipRows"
							v-model.number="config.skip_rows"
							type="number"
							class="input"
							min="0"
							@change="updatePreview"
						>
					</div>
				</div>
			</div>

			<!-- Column Mappings -->
			<div class="column-mappings card">
				<h3>{{ $t('migrate.csv.mapColumns') }}</h3>
				<div class="mappings-grid">
					<div
						v-for="(mapping, index) in config.mapping"
						:key="index"
						class="mapping-row"
					>
						<div class="column-name">
							<strong>{{ mapping.column_name }}</strong>
							<span
								v-if="detectionResult && detectionResult.preview_rows[0]"
								class="preview-value"
							>
								{{ $t('migrate.csv.example') }}: {{ detectionResult.preview_rows[0][index] || '-' }}
							</span>
						</div>
						<div class="select is-fullwidth">
							<select
								v-model="mapping.attribute"
								@change="updatePreview"
							>
								<option
									v-for="attr in TASK_ATTRIBUTES"
									:key="attr"
									:value="attr"
								>
									{{ getAttributeLabel(attr) }}
								</option>
							</select>
						</div>
					</div>
				</div>
			</div>

			<!-- Preview -->
			<div
				v-if="previewResult"
				class="preview-section card"
			>
				<h3>{{ $t('migrate.csv.preview') }}</h3>
				<p>{{ $t('migrate.csv.previewDescription', {count: previewResult.total_rows}) }}</p>

				<div class="preview-tasks">
					<div
						v-for="(task, index) in previewTasks"
						:key="index"
						@click.capture.prevent.stop
					>
						<SingleTaskInProject
							:the-task="task"
							disabled
							:can-mark-as-done="false"
						/>
					</div>
				</div>
			</div>

			<!-- Actions -->
			<div class="actions">
				<XButton
					variant="tertiary"
					@click="resetToUpload"
				>
					{{ $t('misc.cancel') }}
				</XButton>
				<XButton
					:loading="isLoading"
					:disabled="!hasValidMapping || isLoading"
					@click="performImport"
				>
					{{ $t('migrate.csv.import') }}
				</XButton>
			</div>
		</div>

		<!-- Step 3: Success -->
		<div
			v-else-if="step === 'success'"
			class="success-step"
		>
			<Message class="mbe-4">
				{{ successMessage }}
			</Message>
			<XButton :to="{name: 'home'}">
				{{ $t('home.goToOverview') }}
			</XButton>
		</div>
	</div>
</template>

<script setup lang="ts">
import {computed, ref, shallowReactive} from 'vue'
import {useI18n} from 'vue-i18n'

import Message from '@/components/misc/Message.vue'
import SingleTaskInProject from '@/components/tasks/partials/SingleTaskInProject.vue'
import TaskModel from '@/models/task'

import CSVMigrationService, {
	type DetectionResult,
	type ImportConfig,
	type PreviewResult,
	TASK_ATTRIBUTES,
	SUPPORTED_DELIMITERS,
	SUPPORTED_DATE_FORMATS,
} from '@/services/migrator/csvMigration'

import {useTitle} from '@/composables/useTitle'
import {useProjectStore} from '@/stores/projects'
import {getErrorText} from '@/message'

type Step = 'upload' | 'mapping' | 'success'

const {t} = useI18n({useScope: 'global'})

useTitle(() => t('migrate.titleService', {name: 'CSV'}))

const csvService = shallowReactive(new CSVMigrationService())

const step = ref<Step>('upload')
const error = ref('')
const successMessage = ref('')
const isLoading = ref(false)
const uploadInput = ref<HTMLInputElement | null>(null)
const selectedFile = ref<File | null>(null)
const detectionResult = ref<DetectionResult | null>(null)
const previewResult = ref<PreviewResult | null>(null)

const config = ref<ImportConfig>({
	delimiter: ',',
	quote_char: '"',
	date_format: '2006-01-02',
	skip_rows: 0,
	mapping: [],
})

const previewTasks = computed(() => {
	if (!previewResult.value) return []
	return previewResult.value.tasks.map((pt, i) => new TaskModel({
		id: -(i + 1),
		title: pt.title || t('migrate.csv.untitled'),
		description: pt.description || '',
		done: pt.done,
		dueDate: pt.due_date || null,
		startDate: pt.start_date || null,
		endDate: pt.end_date || null,
		priority: pt.priority,
		labels: (pt.labels || []).map((l, li) => ({id: -(li + 1), title: l})),
	}))
})

const hasValidMapping = computed(() => {
	if (!config.value.mapping.length) return false
	// At least one column should be mapped to title
	return config.value.mapping.some(m => m.attribute === 'title')
})

// Map snake_case attribute names to translation keys
function getAttributeLabel(attribute: string): string {
	const attributeMap: Record<string, string> = {
		title: 'task.attributes.title',
		description: 'task.attributes.description',
		due_date: 'task.attributes.dueDate',
		start_date: 'task.attributes.startDate',
		end_date: 'task.attributes.endDate',
		done: 'task.attributes.done',
		priority: 'task.attributes.priority',
		labels: 'task.attributes.labels',
		reminder: 'task.attributes.reminders',
		project: 'project.title',
		ignore: 'migrate.csv.ignore',
	}
	return t(attributeMap[attribute] || attribute)
}

function getDelimiterLabel(delimiter: string): string {
	const labels: Record<string, string> = {
		',': t('migrate.csv.delimiters.comma'),
		';': t('migrate.csv.delimiters.semicolon'),
		'\t': t('migrate.csv.delimiters.tab'),
		'|': t('migrate.csv.delimiters.pipe'),
	}
	return labels[delimiter] || delimiter
}

function getDateFormatLabel(format: string): string {
	const labels: Record<string, string> = {
		'2006-01-02': 'YYYY-MM-DD (2024-01-15)',
		'2006-01-02T15:04:05': 'ISO DateTime (2024-01-15T10:30:00)',
		'02/01/2006': 'DD/MM/YYYY (15/01/2024)',
		'01/02/2006': 'MM/DD/YYYY (01/15/2024)',
		'02-01-2006': 'DD-MM-YYYY (15-01-2024)',
		'01-02-2006': 'MM-DD-YYYY (01-15-2024)',
		'02.01.2006': 'DD.MM.YYYY (15.01.2024)',
		'2006/01/02': 'YYYY/MM/DD (2024/01/15)',
		'2006-01-02 15:04:05': 'DateTime (2024-01-15 10:30:00)',
	}
	return labels[format] || format
}

async function handleFileUpload() {
	const files = uploadInput.value?.files
	if (!files || files.length === 0) return

	selectedFile.value = files[0]
	error.value = ''
	isLoading.value = true

	try {
		const result = await csvService.detect(selectedFile.value)
		detectionResult.value = result

		// Apply detected values
		config.value = {
			delimiter: result.delimiter,
			quote_char: result.quote_char,
			date_format: result.date_format,
			skip_rows: 0,
			mapping: result.suggested_mapping,
		}

		// Get initial preview
		await updatePreview()

		step.value = 'mapping'
	} catch (e) {
		error.value = getErrorText(e)
	} finally {
		isLoading.value = false
	}
}

async function updatePreview() {
	if (!selectedFile.value) return

	isLoading.value = true
	try {
		previewResult.value = await csvService.preview(selectedFile.value, config.value)
	} catch (e) {
		error.value = getErrorText(e)
		previewResult.value = null
	} finally {
		isLoading.value = false
	}
}

async function performImport() {
	if (!selectedFile.value || !hasValidMapping.value) return

	isLoading.value = true
	error.value = ''

	try {
		const result = await csvService.migrate(selectedFile.value, config.value)
		successMessage.value = result.message

		// Reload projects
		const projectStore = useProjectStore()
		await projectStore.loadAllProjects()

		step.value = 'success'
	} catch (e) {
		error.value = getErrorText(e)
	} finally {
		isLoading.value = false
	}
}

function resetToUpload() {
	step.value = 'upload'
	selectedFile.value = null
	detectionResult.value = null
	previewResult.value = null
	error.value = ''
	if (uploadInput.value) {
		uploadInput.value.value = ''
	}
	config.value = {
		delimiter: ',',
		quote_char: '"',
		date_format: '2006-01-02',
		skip_rows: 0,
		mapping: [],
	}
}
</script>

<style lang="scss" scoped>
.csv-migration {
	max-inline-size: 900px;
	margin: 0 auto;
}

.card {
	background: var(--white);
	border-radius: var(--border-radius);
	padding: 1.5rem;
	margin-block-end: 1.5rem;
	box-shadow: var(--shadow-sm);
}

.mapping-header {
	margin-block-end: 1.5rem;

	h2 {
		margin-block-end: 0.5rem;
	}
}

.parsing-options {
	h3 {
		margin-block-end: 1rem;
	}
}

.options-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: 1rem;
}

.option-group {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;

	label {
		font-weight: 500;
	}
}

.column-mappings {
	h3 {
		margin-block-end: 1rem;
	}
}

.mappings-grid {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.mapping-row {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1rem;
	align-items: center;
	padding: 0.75rem;
	background: var(--grey-100);
	border-radius: var(--border-radius);

	@media (width <= 600px) {
		grid-template-columns: 1fr;
	}
}

.column-name {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;

	.preview-value {
		font-size: 0.85rem;
		color: var(--grey-500);
	}
}

.preview-section {
	h3 {
		margin-block-end: 0.5rem;
	}
}

.preview-tasks {
	margin-block-start: 1rem;
}

.actions {
	display: flex;
	gap: 1rem;
	justify-content: flex-end;
	margin-block-start: 1.5rem;
}

.success-step {
	text-align: center;
	padding: 2rem;
}
</style>
