<script setup lang="ts">
import type { Archon } from '@modrinth/api-client'
import {
	ClipboardCopyIcon,
	ClockIcon,
	DownloadIcon,
	EditIcon,
	MoreVerticalIcon,
	RotateCounterClockwiseIcon,
	TrashIcon,
	UserRoundIcon,
	XIcon,
} from '@modrinth/assets'
import { computed } from 'vue'

import { useFormatDateTime } from '../../../composables'
import { defineMessages, useVIntl } from '../../../composables/i18n'
import { commonMessages } from '../../../utils'
import ButtonStyled from '../../base/ButtonStyled.vue'
import OverflowMenu, { type Option as OverflowOption } from '../../base/OverflowMenu.vue'

const { formatMessage } = useVIntl()
const formatDateTime = useFormatDateTime({
	timeStyle: 'short',
	dateStyle: 'long',
})

const emit = defineEmits<{
	(e: 'download' | 'rename' | 'restore' | 'retry'): void
	(e: 'delete', skipConfirmation?: boolean): void
}>()

const props = withDefaults(
	defineProps<{
		backup: Archon.Backups.v1.Backup
		preview?: boolean
		kyrosUrl?: string
		jwt?: string
		showCopyIdAction?: boolean
		showDebugInfo?: boolean
		restoreDisabled?: string
	}>(),
	{
		preview: false,
		kyrosUrl: undefined,
		jwt: undefined,
		showCopyIdAction: false,
		showDebugInfo: false,
		restoreDisabled: undefined,
	},
)

const failedToCreate = computed(
	() => props.backup.status === 'error' || props.backup.status === 'timed_out',
)

const inactiveStates = ['failed', 'cancelled', 'done']

const creating = computed(() => {
	const task = props.backup.task?.create
	if (task && task.progress < 1 && !inactiveStates.includes(task.state)) {
		return true
	}

	if (
		(props.backup.status === 'in_progress' || props.backup.status === 'pending') &&
		!props.backup.task?.restore
	) {
		return true
	}
	return false
})

const restoring = computed(() => {
	const task = props.backup.task?.restore
	if (task && task.progress < 1 && !inactiveStates.includes(task.state)) {
		return true
	}
	return false
})

const failedToRestore = computed(() => props.backup.task?.restore?.state === 'failed')

const activeOperation = computed(() => creating.value || restoring.value)

const backupIcon = computed(() => {
	if (props.backup.automated) {
		return ClockIcon
	}
	return UserRoundIcon
})

const overflowMenuOptions = computed<OverflowOption[]>(() => {
	const options: OverflowOption[] = []

	if (props.showCopyIdAction) {
		options.push({
			id: 'copy-id',
			action: () => copyId(),
		})
	}

	if (!activeOperation.value) {
		if (options.length > 0) {
			options.push({ divider: true })
		}

		options.push({
			id: 'download',
			action: () => emit('download'),
			link: `https://${props.kyrosUrl}/modrinth/v0/backups/${props.backup.id}/download?auth=${props.jwt}`,
			disabled: !props.kyrosUrl || !props.jwt,
		})
	}

	options.push({ id: 'rename', action: () => emit('rename') })

	if (!activeOperation.value) {
		options.push({ divider: true })
		options.push({
			id: 'delete',
			color: 'red',
			action: () => emit('delete'),
		})
	}

	return options
})

async function copyId() {
	await navigator.clipboard.writeText(props.backup.id)
}

// TODO: Uncomment when API supports size field
// const formatBytes = (bytes?: number) => {
// 	if (!bytes) return ''
// 	const mb = bytes / (1024 * 1024)
// 	return `${mb.toFixed(0)} MiB`
// }

const messages = defineMessages({
	restore: {
		id: 'servers.backups.item.restore',
		defaultMessage: 'Restore',
	},
	rename: {
		id: 'servers.backups.item.rename',
		defaultMessage: 'Rename',
	},
	failedToCreateBackup: {
		id: 'servers.backups.item.failed-to-create-backup',
		defaultMessage: 'Failed to create backup',
	},
	failedToRestoreBackup: {
		id: 'servers.backups.item.failed-to-restore-backup',
		defaultMessage: 'Failed to restore from backup',
	},
	auto: {
		id: 'servers.backups.item.auto',
		defaultMessage: 'Auto',
	},
	backupSchedule: {
		id: 'servers.backups.item.backup-schedule',
		defaultMessage: 'Backup schedule',
	},
	manualBackup: {
		id: 'servers.backups.item.manual-backup',
		defaultMessage: 'Manual backup',
	},
})
</script>
<template>
	<div
		class="grid items-center gap-4 rounded-2xl bg-bg-raised p-4 shadow-md"
		:class="
			preview
				? 'grid-cols-1'
				: 'grid-cols-[auto_1fr_auto] md:grid-cols-[minmax(0,1fr)_400px_minmax(0,1fr)]'
		"
	>
		<div class="flex flex-row gap-4 items-center">
			<div
				class="flex size-12 shrink-0 items-center justify-center rounded-2xl border-solid border-[1px] border-surface-5 bg-surface-4 md:size-16"
			>
				<component :is="backupIcon" class="size-7 text-secondary md:size-10" />
			</div>

			<div class="flex min-w-0 flex-col gap-1.5">
				<div class="flex flex-wrap items-center gap-2">
					<span class="truncate font-semibold text-contrast max-w-[400px]">{{ backup.name }}</span>
					<span
						v-if="backup.automated"
						class="rounded-full border-solid border-[1px] border-surface-5 bg-surface-4 px-2.5 py-1 text-sm text-secondary"
					>
						{{ formatMessage(messages.auto) }}
					</span>
				</div>
				<div class="flex items-center gap-1.5 text-sm text-secondary">
					<template v-if="preview">
						<span>{{ formatDateTime(backup.created_at) }}</span>
					</template>
					<template v-else-if="failedToCreate || failedToRestore">
						<XIcon class="size-4 text-red" />
						<span class="text-red">
							{{
								formatMessage(
									failedToCreate ? messages.failedToCreateBackup : messages.failedToRestoreBackup,
								)
							}}
						</span>
					</template>
					<template v-else>
						<!-- TODO: Uncomment when API supports creator_id field -->
						<!-- <template v-if="backup.creator_id && backup.creator_id !== 'auto'">
						<Avatar ... class="size-6 rounded-full" />
						<span>{{ creatorName }}</span>
					</template>
					<template v-else> -->
						<span>
							{{
								formatMessage(backup.automated ? messages.backupSchedule : messages.manualBackup)
							}}
						</span>
						<!-- </template> -->
					</template>
				</div>
			</div>
		</div>

		<div
			v-if="!preview"
			class="col-span-full row-start-2 flex flex-col gap-2 md:col-span-1 md:row-start-auto md:items-center"
		>
			<span class="w-full font-medium text-contrast md:text-center">
				{{ formatDateTime(backup.created_at) }}
			</span>
			<!-- TODO: Uncomment when API supports size field -->
			<!-- <span class="text-secondary">{{ formatBytes(backup.size) }}</span> -->
		</div>

		<div v-if="!preview" class="flex shrink-0 items-center gap-2 md:justify-self-end">
			<ButtonStyled v-if="!activeOperation" color="brand" type="outlined">
				<button
					v-tooltip="props.restoreDisabled"
					class="!border-[1px]"
					:disabled="!!props.restoreDisabled"
					@click="() => emit('restore')"
				>
					<RotateCounterClockwiseIcon class="size-5" />
					{{ formatMessage(messages.restore) }}
				</button>
			</ButtonStyled>
			<ButtonStyled circular type="transparent">
				<OverflowMenu :options="overflowMenuOptions">
					<MoreVerticalIcon class="size-5" />
					<template #copy-id>
						<ClipboardCopyIcon class="size-5" />
						{{ formatMessage(commonMessages.copyIdButton) }}
					</template>
					<template #download>
						<DownloadIcon class="size-5" /> {{ formatMessage(commonMessages.downloadButton) }}
					</template>
					<template #rename>
						<EditIcon class="size-5" /> {{ formatMessage(messages.rename) }}
					</template>
					<template #delete>
						<TrashIcon class="size-5" /> {{ formatMessage(commonMessages.deleteLabel) }}
					</template>
				</OverflowMenu>
			</ButtonStyled>
		</div>

		<pre v-if="!preview && showDebugInfo" class="w-full rounded-xl bg-surface-4 p-2 text-xs">{{
			backup
		}}</pre>
	</div>
</template>
