import { defineAsyncComponent, h } from 'vue';
import { Button, Badge } from 'jingrow-ui';
import { toast } from 'vue-sonner';
import ChangeAppBranchDialog from '../components/marketplace/ChangeAppBranchDialog.vue';
import { confirmDialog, icon, renderDialog } from '../utils/components';
import PlansDialog from '../components/marketplace/PlansDialog.vue';
import CodeReview from '../components/marketplace/CodeReview.vue';
import GenericDialog from '../components/GenericDialog.vue';
import ObjectList from '../components/ObjectList.vue';
import { userCurrency, currency } from '../utils/format';
import { getToastErrorMessage } from '../utils/toast';
import { isMobile } from '../utils/device';
import router from '../router';
import { t } from '../utils/i18n';

export default {
	pagetype: 'Marketplace App',
	whitelistedMethods: {
		removeVersion: 'remove_version',
		addVersion: 'add_version',
		siteInstalls: 'site_installs',
		createApprovalRequest: 'create_approval_request',
		cancelApprovalRequest: 'cancel_approval_request',
		updateListing: 'update_listing',
		markAppReadyForReview: 'mark_app_ready_for_review'
	},
	list: {
		route: '/apps',
		title: t('Marketplace'),
		fields: ['image', 'title', 'status', 'description'],
		columns: [
			{
				label: t('App'),
				fieldname: 'title',
				class: 'font-medium',
				width: 0.3,
				prefix(row) {
					return row.image
						? h('img', {
								src: row.image,
								class: 'w-6 h-6 rounded-sm',
								alt: row.title
						  })
						: h(
								'div',
								{
									class:
										'w-6 h-6 rounded bg-gray-300 text-gray-600 flex items-center justify-center'
								},
								row.title[0].toUpperCase()
						  );
				}
			},
			{
				label: t('Status'),
				type: 'Badge',
				fieldname: 'status',
				width: 0.3
			},
			{
				label: t('Description'),
				fieldname: 'description',
				width: 1.0
			}
		],
		primaryAction() {
			return {
				label: t('New App'),
				variant: 'outline',
				slots: {
					prefix: icon('plus')
				},
				onClick() {
					const NewMarketplaceAppDialog = defineAsyncComponent(() =>
						import('../components/marketplace/NewMarketplaceAppDialog.vue')
					);

					renderDialog(h(NewMarketplaceAppDialog));
				}
			};
		}
	},
	detail: {
		titleField: 'name',
		route: '/apps/:name',
		statusBadge({ documentResource: app }) {
			return { label: app.pg.status };
		},
		breadcrumbs({ items, documentResource: app }) {
			return [
				items[0],
				{
					label: app.pg.title,
					route: `/apps/${app.pg.name}`
				}
			];
		},
		tabs: [
			{
				label: t('Analytics'),
				icon: icon('bar-chart-2'),
				route: 'analytics',
				type: 'Component',
				component: defineAsyncComponent(() =>
					import('../components/marketplace/MarketplaceAppAnalytics.vue')
				),
				props: app => {
					return { app: app.pg.name };
				}
			},
			{
				label: t('Listing'),
				icon: icon('shopping-cart'),
				route: 'listing',
				type: 'Component',
				component: defineAsyncComponent(() =>
					import('../components/MarketplaceAppListing.vue')
				),
				props: app => {
					return { app: app };
				}
			},
			{
				label: t('Versions'),
				icon: icon('package'),
				route: 'versions',
				type: 'list',
				list: {
					pagetype: 'Marketplace App Version',
					filters: app => {
						return { parent: app.pg.name, parenttype: 'Marketplace App' };
					},
					onRowClick: (row, context) => {
						const { listResource: versions, documentResource: app } = context;
						showReleases(row, app);
					},
					fields: [
						'source.repository_owner as repository_owner',
						'source.repository as repository',
						'source.branch as branch'
					],
					columns: [
						{
							label: t('Version'),
							fieldname: 'version',
							width: 0.5
						},
						{
							label: t('Source'),
							fieldname: 'source',
							width: 0.5
						},
						{
							label: t('Repository'),
							width: 0.5,
							format: (value, row) => {
								return `${row.repository_owner}/${row.repository}`;
							}
						},
						{
							label: t('Branch'),
							fieldname: 'branch',
							type: 'Badge',
							width: 0.5
						}
					],
					primaryAction({ listResource: versions, documentResource: app }) {
						return {
							label: t('New Version'),
							slots: {
								prefix: icon('plus')
							},
							onClick() {
								renderDialog(
									h(
										GenericDialog,
										{
											options: {
												title: t('Add version support for {appTitle}', { appTitle: app.pg.title }),
												size: '4xl'
											}
										},
										{
											default: () =>
												h(ObjectList, {
													options: {
														label: t('Version'),
														fieldname: 'version',
														fieldtype: 'ListSelection',
														columns: [
															{
																label: t('Version'),
																fieldname: 'version'
															},
															{
																label: t('Branch'),
																type: 'Select',
																fieldname: 'branch',
																format: (value, row) => {
																	row.selectedOption = value[0];
																	return value.map(v => ({
																		label: v,
																		value: v,
																		onClick: () => {
																			row.selectedOption = v;
																		}
																	}));
																}
															},
															{
																label: '',
																fieldname: '',
																align: 'right',
																type: 'Button',
																width: '5rem',
																Button({ row, listResource: versionsOptions }) {
																	return {
																		label: t('Add'),
																		onClick() {
																			if (app.addVersion.loading) return;
																			toast.promise(
																				app.addVersion.submit({
																					version: row.version,
																					branch: row.selectedOption
																				}),
																				{
																					loading: t('Adding new version...'),
																					success: () => {
																						versions.reload();
																						versionsOptions.reload();
																						return t('New version added');
																					},
																					error: e => getToastErrorMessage(e)
																				}
																			);
																		}
																	};
																}
															}
														],
														resource() {
															return {
																url: 'jcloud.api.marketplace.options_for_version',
																params: {
																	name: app.pg.name
																},
																auto: true
															};
														}
													}
												})
										}
									)
								);
							}
						};
					},
					rowActions({ row, listResource: versions, documentResource: app }) {
						return [
							{
								label: t('Show Releases'),
								slots: {
									prefix: icon('plus')
								},
								onClick() {
									showReleases(row, app);
								}
							},
							{
								label: t('Change Branch'),
								onClick() {
									renderDialog(
										h(ChangeAppBranchDialog, {
											app: app.pg.name,
											source: row.source,
											version: row.version,
											activeBranch: row.branch,
											onBranchChanged() {
												versions.reload();
											}
										})
									);
								}
							},
							{
								label: t('Remove Version'),
								onClick() {
									toast.promise(
										app.removeVersion.submit({ version: row.version }),
										{
											loading: t('Removing version...'),
											success: () => {
												versions.reload();
												return t('Version removed successfully');
											},
											error: e => getToastErrorMessage(e)
										}
									);
								}
							}
						];
					}
				}
			},
			{
				label: t('Pricing'),
				icon: icon('dollar-sign'),
				route: 'pricing',
				type: 'list',
				list: {
					pagetype: 'Marketplace App Plan',
					filters: app => {
						return { app: app.pg.name };
					},
					fields: ['name', 'title', 'price_cny', 'price_usd', 'enabled'],
					columns: [
						{
							label: t('Title'),
							fieldname: 'title'
						},
						{
							label: t('Enabled'),
							type: 'Badge',
							fieldname: 'enabled',
							format: value => {
								return value == 1 ? t('Enabled') : t('Disabled');
							}
						},
						{
							label: t('Price CNY'),
							fieldname: 'price_cny',
							format: value => {
								return currency(value, 'CNY');
							}
						},
						{
							label: t('Price USD'),
							fieldname: 'price_usd',
							format: value => {
								return currency(value, 'USD');
							}
						}
					],
					primaryAction({ listResource: plans, documentResource: app }) {
						return {
							label: t('New Plan'),
							slots: {
								prefix: icon('plus')
							},
							onClick() {
								renderDialog(
									h(PlansDialog, {
										app: app.pg.name,
										onPlanCreated() {
											plans.reload();
										}
									})
								);
							}
						};
					},
					rowActions({ row, listResource: plans, documentResource: app }) {
						return [
							{
								label: t('Edit'),
								onClick() {
									renderDialog(
										h(PlansDialog, {
											app: app.pg.name,
											plan: row,
											onPlanUpdated() {
												plans.reload();
											}
										})
									);
								}
							}
						];
					}
				}
			},
			{
				label: t('Subscriptions'),
				icon: icon('users'),
				route: 'subscription',
				type: 'list',
				list: {
					pagetype: 'Subscription',
					filters: app => {
						return {
							document_type: 'Marketplace App',
							document_name: app.name
						};
					},
					fields: ['site', 'enabled', 'team'],
					filterControls() {
						return [
							{
								type: 'select',
								label: t('Status'),
								class: !isMobile() ? 'w-24' : '',
								fieldname: 'enabled',
								options: ['', t('Active'), t('Disabled')]
							}
						];
					},
					columns: [
						{
							label: t('Site'),
							fieldname: 'site',
							width: 0.6
						},
						{
							label: t('Status'),
							type: 'Badge',
							fieldname: 'enabled',
							width: 0.3,
							format: value => {
								return value ? t('Active') : t('Disabled');
							}
						},
						{
							label: t('Price'),
							fieldname: 'price',
							width: 0.3,
							format: value => {
								return userCurrency(value);
							}
						},
						{
							label: t('Active Days'),
							fieldname: 'active_for',
							width: 0.3,
							format: value => {
								return value + (value == 1 ? ` ${t('day')}` : ` ${t('days')}`);
							}
						}
					]
				}
			}
		],
		actions({ documentResource: app }) {
			return [
				{
					label: t('View in Marketplace'),
					slots: {
						prefix: icon('external-link')
					},
					condition: () => app.pg.status === 'Published',
					onClick() {
						window.open(
							`${window.location.origin}/marketplace/apps/${app.name}`,
							'_blank'
						);
					}
				},
				{
					label: t('Guide'),
					slots: {
						icon: icon('help-circle')
					},
					condition: () => app.pg.status === 'Draft',
					onClick() {
						window.open(
							'https://jingrow.com/docs/marketplace/marketplace-guidelines',
							'_blank'
						);
					}
				},
				{
					label: t('Complete Listing'),
					variant: 'solid',
					slots: {
						prefix: icon('alert-circle')
					},
					condition: () => app.pg.status === 'Draft',
					onClick() {
						let AppListingStepsDialog = defineAsyncComponent(() =>
							import('../components/marketplace/AppListingStepsDialog.vue')
						);

						renderDialog(
							h(AppListingStepsDialog, {
								app: app.pg.name
							})
						);
					}
				},
				{
					label: t('Options'),
					condition: () => app.pg.status === 'Draft',
					options: [
						{
							label: t('Delete'),
							icon: icon('trash-2'),
							condition: () => app.pg.status === 'Draft',
							onClick() {
								confirmDialog({
									title: t('Delete app {appTitle}', { appTitle: app.pg.title }),
									message: t('Are you sure you want to delete this app?'),
									onSuccess({ hide }) {
										toast.promise(app.delete.submit(), {
											loading: t('Deleting app...'),
											success: () => {
												hide();
												router.push({ name: 'Marketplace App List' });
												return t('App deleted successfully');
											},
											error: e => getToastErrorMessage(e)
										});
									}
								});
							}
						}
					]
				}
			];
		}
	}
};

function showReleases(row, app) {
	renderDialog(
		h(
			GenericDialog,
			{
				options: {
					title: t('Releases for {appName} on {branch} branch', { appName: app.pg.name, branch: row.branch }),
					size: '6xl'
				}
			},
			{
				default: () =>
					h(ObjectList, {
						options: {
							label: t('Version'),
							type: 'list',
							pagetype: 'App Release',
							filters: {
								app: app.pg.name,
								source: row.source
							},
							fields: ['message', 'tag', 'author', 'status'],
							orderBy: 'creation desc',
							columns: [
								{
									label: t('Commit Message'),
									fieldname: 'message',
									class: 'w-64',
									width: 0.5
								},
								{
									label: t('Hash'),
									fieldname: 'hash',
									class: 'w-24',
									type: 'Badge',
									width: 0.2,
									format: value => {
										return value.slice(0, 7);
									}
								},
								{
									label: t('Author'),
									fieldname: 'author',
									width: 0.2
								},
								{
									label: t('Status'),
									fieldname: 'status',
									type: 'Badge',
									width: 0.3
								},
								{
									label: t('Code Review'),
									type: 'Component',
									width: 0.2,
									component: ({ row, listResource: releases, app }) => {
										if (
											(row.status === 'Awaiting Approval' ||
												row.status === 'Rejected') &&
											row.screening_status === 'Complete'
										) {
											return h(Button, {
												label: t('Code Review'),
												variant: 'subtle',
												theme: 'blue',
												size: 'sm',
												onClick: () =>
													codeReview(row, app, window.is_system_user)
											});
										}
										return h(Badge, {
											label: row.screening_status || t('Not Started')
										});
									}
								},
								{
									label: '',
									fieldname: '',
									align: 'right',
									type: 'Button',
									width: 0.2,
									Button({ row, listResource: releases }) {
										let label = '';
										let successMessage = '';
										let loadingMessage = '';

										if (row.status === 'Awaiting Approval') {
											label = t('Cancel');
											successMessage = t('Release cancelled');
											loadingMessage = t('Cancelling release...');
										} else if (row.status === 'Draft') {
											label = t('Submit');
											loadingMessage = t('Submitting release for approval...');
											successMessage = t('Release submitted for approval');
										}

										return {
											label: label,
											onClick() {
												toast.promise(
													row.status === 'Awaiting Approval'
														? app.cancelApprovalRequest.submit({
																app_release: row.name
														  })
														: app.createApprovalRequest.submit({
																app_release: row.name
														  }),
													{
														loading: loadingMessage,
														success: () => {
															releases.reload();
															return successMessage;
														},
														error: e => getToastErrorMessage(e)
													}
												);
											}
										};
									}
								}
							]
						}
					})
			}
		)
	);
}

function codeReview(row, app, isSystemUser) {
	renderDialog(
		h(CodeReview, {
			row: row,
			app: app,
			isSystemUser: isSystemUser
		})
	);
}