use std::{collections::HashMap};

use serde::{Serialize, Deserialize};
use utoipa::{ToSchema, IntoParams};

#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct AuthReturn {
    #[schema(example = false)]
    pub moderator: bool,
    #[schema(example = false)]
    pub admin: bool,
}

// Game Structs

#[derive(Serialize, Deserialize, ToSchema, Debug, IntoParams)]
pub struct GetGameParam {
    #[schema(example = 1)]
    pub game_id: i32,
}

#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct PostGameParams {
    #[schema(example = "Game XY")]
    pub game_name: String,
}

#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct UpdateGameParams {
    #[schema(example = 1)]
    pub game_id: i32,
    #[schema(example = "Game XY")]
    pub game_name: String,
}

#[derive(Serialize, Deserialize, ToSchema, Debug, IntoParams)]
pub struct DeleteGameParam {
    #[schema(example = 1)]
    pub game_id: i32,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct FullViewData {
    pub games: HashMap<i32, ChellarisGameLegacy>,
    pub ethics: HashMap<i32, Ethic>,
    pub species: HashMap<i32, Species>,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct ChellarisGameLegacy {
    pub id: i32,
    pub name: String,
    pub groups: HashMap<i32, ChellarisGameGroupLegacy>,
    pub empires: HashMap<i32, ChellarisEmpireLegacy>,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct ChellarisGameFlat {
    pub id: i32,
    pub name: String,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct ChellarisGame {
    pub id: i32,
    pub name: String,
    pub empires: HashMap<i32, ChellarisEmpireFlat>,
    pub groups: HashMap<i32, ChellarisGroupFlat>
}

// Group Structs

#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct PostGroupParams {
    #[schema(example = "Group XY")]
    pub group_name: String,
    #[schema(example = 1)]
    pub game_id: i32
}

#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct UpdateGroupParams {
    #[schema(example = 1)]
    pub group_id: i32,
    #[schema(example = 1)]
    pub game_id: i32,
    #[schema(example = "Group XY")]
    pub group_name: String
}

#[derive(Serialize, Deserialize, ToSchema, Debug, IntoParams)]
pub struct DeleteGroupParams {
    #[schema(example = 1)]
    pub group_id: i32,
    #[schema(example = 1)]
    pub game_id: i32,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct ChellarisGroupFlat {
    pub id: i32,
    pub name: String,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct ChellarisGameGroupLegacy {
    pub id: i32,
    pub name: String,
}

// Empire Structs

#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct PostEmpireParams {
    #[schema(example = 1)]
    pub game_id: i32,
    #[schema(example = 1)]
    pub group_id: i32,
    #[schema(example = "Example Empire")]
    pub empire_name: String,
    #[schema(example = true)]
    pub gestalt: bool,
    #[schema(example = 1)]
    pub portrait_id: i32,
    #[schema(example = 1)]
    pub portrait_group_id: i32,
    #[schema(example = json!([
        { "ethic_id": 1, "fanatic": false }, 
        { "ethic_id": 2, "fanatic": true }, 
        { "ethic_id": 3, "fanatic": false },
    ]))]
    pub ethics: Vec<EmpireEthic>,
    #[schema(example = "UsernameExample")]
    pub discord_user: Option<String>,
}

#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct UpdateEmpireParams {
    #[schema(example = 1)]
    pub empire_id: i32,
    #[schema(example = 1)]
    pub game_id: Option<i32>,
    #[schema(example = 1)]
    pub group_id: Option<i32>,
    #[schema(example = "Example Empire")]
    pub empire_name: Option<String>,
    #[schema(example = true)]
    pub gestalt: Option<bool>,
    #[schema(example = 1)]
    pub portrait_id: Option<i32>,
    #[schema(example = 1)]
    pub portrait_group_id: Option<i32>,
    #[schema(example = json!([
        { "ethic_id": 1, "fanatic": false }, 
        { "ethic_id": 2, "fanatic": true }, 
        { "ethic_id": 3, "fanatic": false },
    ]))]
    pub ethics: Option<Vec<EmpireEthic>>,
    #[schema(example = "UsernameExample")]
    pub discord_user: Option<String>,
}

#[derive(Serialize, Deserialize, ToSchema, Debug, IntoParams)]
pub struct DeleteEmpireParams {
    #[schema(example = 1)]
    pub game_id: i32,
    #[schema(example = 1)]
    pub group_id: i32,
    #[schema(example = 1)]
    pub empire_id: i32,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct ChellarisEmpireFlat {
    pub id: i32,
    pub group: i32,
    pub game: i32,
    pub name: String,
    pub discord_user: Option<String>,
    pub gestalt: bool,
    pub portrait_id: i32,
    pub portrait_group_id: i32,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct ChellarisEmpire {
    pub id: i32,
    pub group: i32,
    pub game: i32,
    pub name: String,
    pub discord_user: Option<String>,
    pub gestalt: bool,
    pub portrait_id: i32,
    pub portrait_group_id: i32,
    pub ethics: HashMap<i32, EmpireEthic>,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct ChellarisEmpireLegacy {
    pub id: i32,
    pub group: i32,
    pub gestalt: bool,
    pub machine: bool,
    pub empire_portrait: i32,
    pub empire_portrait_group: i32,
    pub discord_user: Option<String>,
    pub ethics: HashMap<i32, EmpireEthicLegacy>,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct Ethic {
    pub id: i32,
    pub display: String,
    pub machine: bool,
}

#[derive(Serialize, Deserialize, ToSchema, Debug, Clone)]
pub struct EmpireEthic {
    #[schema(example = "1")]
    pub ethic_id: i32,
    #[schema(example = "true")]
    pub fanatic: bool,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct EmpireEthicLegacy {
    pub id: i32,
    pub display: String,
    pub machine: bool,
    pub fanatic: bool,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct Species {
    pub id: i32,
    pub display: String,
    pub portraits: HashMap<i32, Portrait>,
}

#[derive(Serialize, ToSchema, Debug, Clone)]
pub struct Portrait {
    pub id: i32,
    pub hires: String,
    pub lores: Option<String>,
}