import { integer, sqliteTable, text, real, unique } from 'drizzle-orm/sqlite-core';
import { user } from './auth.schema';
import type { InferSelectModel } from 'drizzle-orm';

// Define devil fruit types
export type DevilFruitType = 'Paramecia' | 'Zoan' | 'Logia' | 'Unknown';

export type Status = 'Alive' | 'Dead' | 'Unknown';
export type FriendshipStatus = 'pending' | 'accepted' | 'declined';

// Define the site config table schema
export const config = sqliteTable('config', {
	key: text('key').primaryKey(),
	value: text('value')
});

// Define the arc table schema
export const arc = sqliteTable('arc', {
	id: text('id').primaryKey(),
	name: text('name').notNull(),
	frName: text('fr_name'),
	startChapter: integer('start_chapter').notNull(),
	endChapter: integer('end_chapter'),
	url: text('url')
});

export type Arc = InferSelectModel<typeof arc>;

// Define the devil fruit table schema
export const devilFruit = sqliteTable('devil_fruit', {
	id: text('id').primaryKey(),
	name: text('name').notNull().unique(),
	type: text('type').$type<DevilFruitType>(),
	url: text('url')
});

export type DevilFruit = InferSelectModel<typeof devilFruit>;

// Define the character table schema
export const character = sqliteTable('character', {
	id: text('id').primaryKey(),
	name: text('name').notNull(),
	frName: text('fr_name'),
	gender: text('gender'),
	age: integer('age'),
	affiliation: text('affiliation'),
	frAffiliation: text('fr_affiliation'),
	devilFruitId: text('devil_fruit_id').references(() => devilFruit.id),
	hakiObservation: integer('haki_observation', { mode: 'boolean' }).default(false),
	hakiArmament: integer('haki_armament', { mode: 'boolean' }).default(false),
	hakiConqueror: integer('haki_conqueror', { mode: 'boolean' }).default(false),
	bounty: integer('bounty').default(0),
	height: real('height'),
	origin: text('origin'),
	frOrigin: text('fr_origin'),
	firstAppearance: integer('first_appearance').notNull(),
	pictureUrl: text('picture_url'),
	epithets: text('epithets', { mode: 'json' }).$type<string[]>(),
	frEpithets: text('fr_epithets', { mode: 'json' }).$type<string[]>(),
	status: text('status').$type<Status | null>(),
	arcId: text('arc_id').references(() => arc.id, { onDelete: 'set null' }),
	url: text('url'),
	frUrl: text('fr_url'),
	isInDailyMode: integer('is_in_daily_mode', { mode: 'boolean' }).default(false)
});

export type Character = InferSelectModel<typeof character>;

// Define the character scrape validation table schema
export const characterScrapeValidation = sqliteTable('character_scrape_validation', {
	id: text('id').primaryKey(),
	name: text('name').notNull(),
	frName: text('fr_name'),
	gender: text('gender'),
	age: integer('age'),
	affiliation: text('affiliation'),
	frAffiliation: text('fr_affiliation'),
	devilFruitId: text('devil_fruit_id').references(() => devilFruit.id, { onDelete: 'set null' }),
	hakiObservation: integer('haki_observation', { mode: 'boolean' }).default(false),
	hakiArmament: integer('haki_armament', { mode: 'boolean' }).default(false),
	hakiConqueror: integer('haki_conqueror', { mode: 'boolean' }).default(false),
	bounty: integer('bounty'),
	height: real('height'),
	origin: text('origin'),
	frOrigin: text('fr_origin'),
	firstAppearance: integer('first_appearance').notNull(),
	pictureUrl: text('picture_url'),
	epithets: text('epithets', { mode: 'json' }).$type<string[]>(),
	frEpithets: text('fr_epithets', { mode: 'json' }).$type<string[]>(),
	status: text('status').$type<Status | null>(),
	arcId: text('arc_id').references(() => arc.id, { onDelete: 'set null' }),
	url: text('url'),
	frUrl: text('fr_url'),
	isDeleted: integer('is_deleted', { mode: 'boolean' }).default(false),
});

export type CharacterScrapeValidation = InferSelectModel<typeof characterScrapeValidation>;

// Define the character history table schema
export const characterHistory = sqliteTable('character_history', {
	id: text('id')
		.primaryKey()
		.$defaultFn(() => crypto.randomUUID()),
	characterId: text('character_id').references(() => character.id, { onDelete: 'cascade' }),
	date: integer('date').notNull().unique(),
	won: integer('won').notNull().default(0),
	createdAt: integer('created_at').notNull().$default(() => Date.now()),
	updatedAt: integer('updated_at').notNull().$default(() => Date.now()),
});

export type CharacterHistory = InferSelectModel<typeof characterHistory>;

// Define the user character history table schema
export const userCharacterHistory = sqliteTable('user_character_history', {
	id: text('id')
		.primaryKey()
		.$defaultFn(() => crypto.randomUUID()),
	userId: text('user_id').references(() => user.id, { onDelete: 'cascade' }),
	characterHistoryId: text('character_history_id').references(() => characterHistory.id, { onDelete: 'cascade' }),
	tryCount: integer('try_count').notNull(),
	triedCharacterIds: text('tried_character_ids', { mode: 'json' }).$type<string[]>(),
	createdAt: integer('created_at').notNull().$default(() => Date.now())
}, (table) => [
	unique().on(table.userId, table.characterHistoryId)
]);

export type UserCharacterHistory = InferSelectModel<typeof userCharacterHistory>;

// Define the devil fruit history table schema
export const devilFruitHistory = sqliteTable('devil_fruit_history', {
	id: text('id')
		.primaryKey()
		.$defaultFn(() => crypto.randomUUID()),
	devilFruitId: text('devil_fruit_id').references(() => devilFruit.id, { onDelete: 'cascade' }),
	date: integer('date').notNull().unique(),
	won: integer('won').notNull().default(0),
	createdAt: integer('created_at').notNull().$default(() => Date.now()),
	updatedAt: integer('updated_at').notNull().$default(() => Date.now()),
});

export type DevilFruitHistory = InferSelectModel<typeof devilFruitHistory>;

// Define the friendship table schema (friend requests + accepted friends)
export const friendship = sqliteTable('friendship', {
	id: text('id')
		.primaryKey()
		.$defaultFn(() => crypto.randomUUID()),
	requesterId: text('requester_id')
		.notNull()
		.references(() => user.id, { onDelete: 'cascade' }),
	addresseeId: text('addressee_id')
		.notNull()
		.references(() => user.id, { onDelete: 'cascade' }),
	status: text('status').$type<FriendshipStatus>().notNull().default('pending'),
	createdAt: integer('created_at').notNull().$default(() => Date.now()),
	updatedAt: integer('updated_at').notNull().$default(() => Date.now()),
}, (table) => [
	unique().on(table.requesterId, table.addresseeId)
]);

export type Friendship = InferSelectModel<typeof friendship>;

export * from './auth.schema';
