<template>
	<Dialog
		v-model="show"
		:options="{
			title: dialogTitle,
			size: '2xl',
		}"
	>
		<template #body-content>
			<template v-if="updatableApps.length > 0">
				<GenericList :options="listOptions" />
				<div class="mt-4 flex flex-col space-y-4">
					<DateTimeControl
						v-model="scheduledTime"
						label="Schedule Time in IST"
					/>
					<div class="flex flex-col space-y-2">
						<FormControl
							label="Skip failing patches if any"
							type="checkbox"
							v-model="skipFailingPatches"
						/>
						<FormControl
							label="Skip taking backup for this update"
							type="checkbox"
							v-model="skipBackups"
							v-if="!$site.pg.group_public"
						/>
						<div
							class="flex items-center rounded border border-gray-200 bg-gray-100 p-4 text-sm text-gray-600"
							v-if="skipBackups"
						>
							<lucide-alert-triangle class="mr-4 inline-block h-6 w-6" />
							<div>
								If the update fails, rollback will not occur as there is no
								backup. You will have to manually fix the issues over
								<a
									href="https://docs.framework.jingrow.com/cloud/benches/ssh"
									target="_blank"
									class="underline"
									>ssh</a
								>.
							</div>
						</div>
					</div>
				</div>
			</template>
			<div v-else class="text-center text-base text-gray-600">
				No apps to update
			</div>
			<ErrorMessage class="mt-4" :message="$site.scheduleUpdate.error" />
		</template>
		<template #actions>
			<Button
				v-if="existingUpdate"
				class="w-full"
				variant="solid"
				label="Edit Update"
				@click="editUpdate"
			/>
			<Button
				v-else
				class="w-full"
				variant="solid"
				:theme="skipBackups ? 'red' : 'gray'"
				:loading="$site.scheduleUpdate.loading"
				:label="`Update ${
					scheduledTime ? `at ${scheduledTimeInLocal}` : 'Now'
				}`"
				@click="scheduleUpdate"
			/>
		</template>
	</Dialog>
</template>
<script>
import { getCachedDocumentResource } from 'frappe-ui';
import DateTimeControl from './DateTimeControl.vue';
import GenericList from './GenericList.vue';
import dayjs, { dayjsIST } from '../utils/dayjs';
import { toast } from 'vue-sonner';

export default {
	name: 'SiteUpdateDialog',
	props: {
		site: {
			type: String,
			required: true,
		},
		existingUpdate: String,
	},
	components: {
		GenericList,
		DateTimeControl,
	},
	data() {
		return {
			show: true,
			skipFailingPatches: false,
			scheduledTime: '',
			skipBackups: false,
		};
	},
	resources: {
		siteUpdate() {
			return {
				// for some reason, type: document won't work after the first time
				// TODO: investigate why
				url: 'press.api.client.get',
				params: {
					doctype: 'Site Update',
					name: this.existingUpdate,
				},
				auto: !!this.existingUpdate,
				onSuccess: (pg) => {
					this.initializeValues(pg);
				},
			};
		},
	},
	computed: {
		scheduledTimeInIST() {
			if (!this.scheduledTime) return;
			return dayjsIST(this.scheduledTime).format('YYYY-MM-DDTHH:mm');
		},
		scheduledTimeInLocal() {
			return dayjs(this.scheduledTime).format('lll');
		},
		listOptions() {
			return {
				data: this.updatableApps.filter(
					(app) => app.current_hash !== app.next_hash,
				),
				columns: [
					{
						label: 'App',
						fieldname: 'app',
						format(value, row) {
							return row.title || value;
						},
					},
					{
						label: 'Current Version',
						type: 'Badge',
						format(value, row) {
							return row.will_branch_change
								? row.current_branch
								: row.current_tag || row.current_hash.slice(0, 7);
						},
						link(value, row) {
							if (row.will_branch_change) {
								return `${row.repository_url}/tree/${row.current_branch}`;
							}
							if (row.current_tag) {
								return `${row.repository_url}/releases/tag/${row.current_tag}`;
							}
							if (row.current_hash) {
								return `${row.repository_url}/commit/${row.current_hash}`;
							}
						},
					},
					{
						label: 'Next Version',
						type: 'Badge',
						format(value, row) {
							return row.will_branch_change
								? row.branch
								: row.next_tag || row.next_hash.slice(0, 7);
						},
						link(value, row) {
							if (row.will_branch_change) {
								return `${row.repository_url}/tree/${row.branch}`;
							}
							if (row.next_tag) {
								return `${row.repository_url}/releases/tag/${row.next_tag}`;
							}
							if (row.next_hash) {
								return `${row.repository_url}/commit/${row.next_hash}`;
							}
						},
					},
				],
			};
		},
		updatableApps() {
			if (!this.$site.pg.update_information.update_available) return [];
			let installedApps = this.$site.pg.update_information.installed_apps.map(
				(d) => d.app,
			);
			return this.$site.pg.update_information.apps.filter((app) =>
				installedApps.includes(app.app),
			);
		},
		$site() {
			return getCachedDocumentResource('Site', this.site);
		},
		siteUpdate() {
			return this.$resources.siteUpdate;
		},
		dialogTitle() {
			if (this.existingUpdate) return 'Edit Scheduled Update';
			else return 'Updates Available';
		},
	},
	methods: {
		scheduleUpdate() {
			this.$site.scheduleUpdate.submit(
				{
					skip_failing_patches: this.skipFailingPatches,
					skip_backups: this.skipBackups,
					scheduled_time: this.scheduledTimeInIST,
				},
				{
					onSuccess: () => {
						this.$site.reload();
						this.show = false;
						this.$router.push({ name: 'Site Detail Updates' });
					},
				},
			);
		},
		editUpdate() {
			toast.promise(
				this.$site.editScheduledUpdate.submit({
					name: this.existingUpdate,
					skip_failing_patches: this.skipFailingPatches,
					skip_backups: this.skipBackups,
					scheduled_time: this.scheduledTimeInIST,
				}),
				{
					loading: 'Editing scheduled update...',
					success: () => {
						this.show = false;
						this.$site.reload();
						this.siteUpdate.reload();
						return 'Scheduled update edited successfully';
					},
					error: (err) => {
						return err.messages.length
							? err.messages[0]
							: err.message || 'Failed to edit scheduled update';
					},
				},
			);
		},
		initializeValues(pg) {
			this.skipFailingPatches = pg.skipped_failing_patches;
			this.skipBackups = pg.skipped_backups;
			this.scheduledTime = dayjs(pg.scheduled_time).format('YYYY-MM-DDTHH:mm');
		},
	},
};
</script>
