use gotcha_gitea::{
    PullFileSource, activity, comment_can_edit, diff, models, pull_file_source, pull_state,
};

use crate::domain::{
    HistoryCommit, HomeData, IssueDetails, IssueEditorData, IssueFilter, MilestoneDetails,
    PullDetails, PullFilter, RepositoryData, civil_from_days, days_from_civil, parse_api_date,
};

#[derive(Clone, Copy, Debug, Eq, PartialEq, uniffi::Enum)]
pub enum WorkItemState {
    Open,
    Closed,
    Unknown,
}

#[derive(Clone, uniffi::Record)]
pub struct ServerRow {
    pub id: String,
    pub name: String,
    pub url: String,
}

#[derive(Clone, uniffi::Record)]
pub struct ServerEditor {
    pub name: String,
    pub url: String,
    pub provider: crate::ServerProvider,
}

#[derive(Clone, uniffi::Record)]
pub struct RepositoryRow {
    pub name: String,
    pub owner: String,
    pub description: String,
    pub meta: String,
    pub favorite: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct RepositoryListPage {
    pub rows: Vec<RepositoryRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct LabelRow {
    pub name: String,
    pub color: String,
    pub light: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct IssueRow {
    pub number: i64,
    pub state: WorkItemState,
    pub title: String,
    pub summary: String,
    pub meta: String,
    pub milestone: String,
    pub labels: Vec<LabelRow>,
}

#[derive(Clone, uniffi::Record)]
pub struct IssueListPage {
    pub rows: Vec<IssueRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct PullRow {
    pub number: i64,
    pub owner: String,
    pub repository: String,
    pub state: WorkItemState,
    pub title: String,
    pub summary: String,
    pub meta: String,
}

#[derive(Clone, uniffi::Record)]
pub struct CommentRow {
    pub id: i64,
    pub author: String,
    pub body: String,
    pub meta: String,
    pub can_edit: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct IssuePage {
    pub title: String,
    pub state: WorkItemState,
    pub meta: String,
    pub milestone: String,
    pub labels: Vec<LabelRow>,
    pub body: String,
    pub comments: Vec<CommentRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct IssueEditorLabel {
    pub id: i64,
    pub name: String,
    pub selected: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct IssueEditorMilestone {
    pub id: i64,
    pub title: String,
    pub selected: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct IssueEditorPage {
    pub title: String,
    pub body: String,
    pub due_date: Option<i64>,
    pub closed: bool,
    pub labels: Vec<IssueEditorLabel>,
    pub milestones: Vec<IssueEditorMilestone>,
}

#[derive(Clone, uniffi::Record)]
pub struct IssueFilterOptions {
    pub milestones: Vec<String>,
    pub labels: Vec<String>,
    pub unavailable_labels: Vec<String>,
    pub selected_milestone: String,
    pub selected_labels: Vec<String>,
    pub search_text: String,
}

#[derive(Clone, uniffi::Record)]
pub struct MilestoneRow {
    pub id: i64,
    pub state: WorkItemState,
    pub title: String,
    pub description: String,
    pub meta: String,
    pub has_issues: bool,
    pub progress: f64,
    pub progress_accessibility: String,
}

#[derive(Clone, uniffi::Record)]
pub struct MilestonePage {
    pub milestone: MilestoneRow,
    pub issues: Vec<IssueRow>,
    pub pulls: Vec<PullRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct MilestoneListPage {
    pub rows: Vec<MilestoneRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct MilestoneEditorPage {
    pub title: String,
    pub description: String,
    pub due_date: Option<i64>,
    pub closed: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct PullFilterOptions {
    pub milestones: Vec<String>,
    pub selected_milestone: String,
    pub search_text: String,
}

#[derive(Clone, uniffi::Record)]
pub struct PullPage {
    pub title: String,
    pub state: WorkItemState,
    pub meta: String,
    pub body: String,
    pub files_ref: String,
    pub files: Vec<FileRow>,
    pub comments: Vec<CommentRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct PullListPage {
    pub rows: Vec<PullRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct CommitRow {
    pub sha: String,
    pub title: String,
    pub detail: String,
    pub branch_label: Option<String>,
    pub top_lanes: Vec<u32>,
    pub bottom_lanes: Vec<u32>,
    pub node_lane: Option<u32>,
    pub top_connections: Vec<u32>,
    pub bottom_connections: Vec<u32>,
}

#[derive(Clone, uniffi::Record)]
pub struct CommitPage {
    pub branches: Vec<String>,
    pub commits: Vec<CommitRow>,
    pub lane_count: u32,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct CommitMetadataRow {
    pub label: String,
    pub value: String,
    pub monospaced: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct CommitDetailsPage {
    pub title: String,
    pub description: String,
    pub metadata: Vec<CommitMetadataRow>,
    pub files: Vec<FileRow>,
}

#[derive(Clone, uniffi::Record)]
pub struct FileRow {
    pub path: String,
    pub status: String,
}

#[derive(Clone, uniffi::Record)]
pub struct FileListPage {
    pub rows: Vec<FileRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct RepositoryContentRow {
    pub name: String,
    pub path: String,
    pub kind: RepositoryContentKind,
    pub size: i64,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, uniffi::Enum)]
pub enum RepositoryContentKind {
    Directory,
    File,
}

#[derive(Clone, uniffi::Record)]
pub struct RepositoryFilePage {
    pub name: String,
    pub kind: RepositoryFileKind,
    pub language: String,
    pub text: String,
    pub data: Vec<u8>,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, uniffi::Enum)]
pub enum RepositoryFileKind {
    Markdown,
    Source,
    Preview,
}

#[derive(Clone, uniffi::Record)]
pub struct DiffLine {
    pub old_number: String,
    pub new_number: String,
    pub text: String,
    pub kind: DiffLineKind,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, uniffi::Enum)]
pub enum DiffLineKind {
    Addition,
    Removal,
    Hunk,
    Header,
    Context,
}

#[derive(Clone, uniffi::Record)]
pub struct DiffPage {
    pub title: String,
    pub columns: u32,
    pub lines: Vec<DiffLine>,
}

#[derive(Clone, uniffi::Record)]
pub struct ActivityRow {
    pub icon: ActivityIcon,
    pub title: String,
    pub detail: String,
    pub meta: String,
    pub target: ActivityTargetKind,
    pub owner: String,
    pub repository: String,
    pub number: i64,
    pub sha: String,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, uniffi::Enum)]
pub enum ActivityIcon {
    Repository,
    Issue,
    PullRequest,
    Branch,
    Tag,
    Push,
    Release,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, uniffi::Enum)]
pub enum ActivityTargetKind {
    None,
    Repository,
    Issue,
    PullRequest,
    Commit,
}

#[derive(Clone, Copy, Debug, uniffi::Enum)]
pub enum HomeActivityFilter {
    All,
    Issues,
    PullRequests,
}

impl From<HomeActivityFilter> for gotcha_gitea::ActivityFilter {
    fn from(filter: HomeActivityFilter) -> Self {
        match filter {
            HomeActivityFilter::All => Self::All,
            HomeActivityFilter::Issues => Self::Issues,
            HomeActivityFilter::PullRequests => Self::PullRequests,
        }
    }
}

#[derive(Clone, uniffi::Record)]
pub struct HeatCell {
    pub level: u32,
    pub timestamp: i64,
}

#[derive(Clone, uniffi::Record)]
pub struct HomePage {
    pub server_name: String,
    pub activities: Vec<ActivityRow>,
    pub heat_cells: Vec<HeatCell>,
    pub contribution_count: i64,
    pub next_page: Option<u32>,
}

#[derive(Clone, uniffi::Record)]
pub struct ServerActivityPage {
    pub rows: Vec<ActivityRow>,
    pub has_more: bool,
}

#[derive(Clone, Copy, Debug, uniffi::Enum)]
pub enum NotificationStatus {
    Open,
    Closed,
}

#[derive(Clone, uniffi::Record)]
pub struct NotificationRow {
    pub id: i64,
    pub server_id: String,
    pub title: String,
    pub detail: String,
    pub meta: String,
    pub unread: bool,
    pub target: ActivityTargetKind,
    pub owner: String,
    pub repository: String,
    pub number: i64,
    pub sha: String,
}

#[derive(Clone, uniffi::Record)]
pub struct NotificationListPage {
    pub rows: Vec<NotificationRow>,
    pub has_more: bool,
}

#[derive(Clone, uniffi::Record)]
pub struct WidgetActivityPage {
    pub server_name: String,
    pub rows: Vec<ActivityRow>,
}

#[derive(Clone, uniffi::Record)]
pub struct WidgetPullPage {
    pub server_name: String,
    pub rows: Vec<PullRow>,
}

mod details;
mod files;
mod helpers;
mod home;
mod lists;
mod notifications;

pub use details::*;
pub use files::*;
pub use helpers::compact_date;
pub use home::*;
pub use lists::*;
pub use notifications::*;

#[cfg(test)]
mod tests;
