use std::collections::BTreeSet;

use gotcha_gitea::models;
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum AppearanceMode {
    Light,
    Dark,
    #[default]
    #[serde(other)]
    Auto,
}

impl AppearanceMode {
    pub fn index(self) -> i32 {
        match self {
            Self::Auto => 0,
            Self::Light => 1,
            Self::Dark => 2,
        }
    }

    pub fn from_index(index: i32) -> Option<Self> {
        match index {
            0 => Some(Self::Auto),
            1 => Some(Self::Light),
            2 => Some(Self::Dark),
            _ => None,
        }
    }
}

#[derive(Clone, Deserialize, Serialize)]
pub struct Server {
    pub name: String,
    pub url: String,
    #[serde(skip)]
    pub token: String,
}

#[derive(Deserialize, Serialize)]
pub struct Preferences {
    #[serde(default)]
    pub servers: Vec<Server>,
    #[serde(default)]
    pub favorites: BTreeSet<String>,
    #[serde(default)]
    pub last_server: Option<usize>,
    #[serde(default = "open_status")]
    pub issue_status: String,
    #[serde(default = "open_status")]
    pub pull_status: String,
    #[serde(default)]
    pub appearance: AppearanceMode,
}

impl Default for Preferences {
    fn default() -> Self {
        Self {
            servers: Vec::new(),
            favorites: BTreeSet::new(),
            last_server: None,
            issue_status: open_status(),
            pull_status: open_status(),
            appearance: AppearanceMode::default(),
        }
    }
}

#[derive(Clone)]
pub struct RepositoryData {
    pub owner: String,
    pub name: String,
    pub description: String,
    pub language: String,
    pub open_issues: i64,
    pub updated: String,
    pub default_branch: String,
}

#[derive(Clone)]
pub struct HistoryCommit {
    pub commit: models::Commit,
    pub top_lanes: Vec<usize>,
    pub bottom_lanes: Vec<usize>,
    pub node_lane: Option<usize>,
    pub connections: Vec<usize>,
    pub refs: Vec<String>,
}

#[derive(Default)]
pub struct State {
    pub preferences: Preferences,
    pub active_server: Option<usize>,
    pub repositories: Vec<RepositoryData>,
}

pub struct HomeData {
    pub activities: Vec<models::Activity>,
    pub heatmap: Vec<models::UserHeatmapData>,
}

pub struct IssueDetails {
    pub issue: models::Issue,
    pub comments: Vec<models::Comment>,
}

pub struct MilestoneDetails {
    pub milestone: models::Milestone,
    pub issues: Vec<models::Issue>,
}

pub struct PullDetails {
    pub pull: models::PullRequest,
    pub comments: Vec<models::Comment>,
    pub files: Vec<models::ChangedFile>,
}

pub fn open_status() -> String {
    "open".into()
}
