use crate::{language::language, page::Page, AppState};
use axum::{
    extract::{Path, Query, State},
    http::HeaderMap,
    response::{IntoResponse, Redirect, Response},
    routing::{get, post},
    Form, Router,
};
use axum_extra::extract::{
    cookie::{Cookie, Expiration},
    CookieJar, PrivateCookieJar,
};
use maud::{html, Markup};
use serde::Deserialize;
use std::collections::HashMap;
use time::OffsetDateTime;
use uuid::Uuid;

#[derive(Deserialize)]
struct LoginForm {
    password: String,
}

#[derive(Deserialize)]
struct CameraForm {
    uuid: String,
    name: String,
    desc: Option<String>,
}

#[derive(Deserialize)]
struct DeleteCameraForm {
    uuid: String,
}

#[derive(Deserialize)]
struct EditCameraForm {
    name: String,
    desc: Option<String>,
}

async fn login_page(cookies: CookieJar, headers: HeaderMap) -> Markup {
    let lang = language(&cookies, &headers);
    rust_i18n::set_locale(lang.to_locale());

    Page::new(lang).content(html! {
        h1 { "Admin Login" }
        form method="POST" action="/admin/login" {
            fieldset {
                label for="password" { "Password:" }
                input
                    type="password"
                    name="password"
                    id="password"
                    required;
                input type="submit" value="Login";
            }
        }
    })
}

async fn login(
    State(state): State<AppState>,
    private_cookies: PrivateCookieJar,
    Form(form): Form<LoginForm>,
) -> Response {
    if form.password == state.admin_password {
        // Set secure admin session cookie
        let expiration_date = OffsetDateTime::now_utc() + time::Duration::days(30);
        let mut cookie = Cookie::new("admin_session", "authenticated");
        cookie.set_expires(Expiration::DateTime(expiration_date));
        cookie.set_http_only(true);
        cookie.set_secure(true);
        cookie.set_path("/");

        let updated_cookies = private_cookies.add(cookie);
        (updated_cookies, Redirect::to("/protected")).into_response()
    } else {
        // Invalid password, redirect back to login
        Redirect::to("/admin/login").into_response()
    }
}

async fn logout(private_cookies: PrivateCookieJar) -> Response {
    // Remove admin session cookie
    let expired_cookie = Cookie::build(("admin_session", ""))
        .expires(Expiration::DateTime(
            OffsetDateTime::now_utc() - time::Duration::days(1),
        ))
        .http_only(true)
        .secure(true)
        .path("/")
        .build();

    let updated_cookies = private_cookies.add(expired_cookie);
    (updated_cookies, Redirect::to("/")).into_response()
}

async fn protected_page(
    private_cookies: PrivateCookieJar,
    cookies: CookieJar,
    headers: HeaderMap,
) -> Response {
    // Check if admin is authenticated
    if private_cookies.get("admin_session").is_none() {
        return Redirect::to("/admin/login").into_response();
    }

    let lang = language(&cookies, &headers);
    rust_i18n::set_locale(lang.to_locale());

    let markup = Page::new(lang).content(html! {
        h1 { "Protected Admin Area" }
        p { "Welcome to the admin area! This is a protected route." }
        p { "Only authenticated administrators can access this page." }

        h2 { "Camera Management" }
        p { "Manage cameras in the system." }
        a href="/admin/cameras/add" { "Add Camera" }
        " | "
        a href="/admin/cameras" { "Manage Cameras" }

        form method="POST" action="/admin/logout" {
            input type="submit" value="Logout" class="secondary";
        }
    });

    markup.into_response()
}

async fn add_camera_page(
    private_cookies: PrivateCookieJar,
    cookies: CookieJar,
    headers: HeaderMap,
    Query(params): Query<HashMap<String, String>>,
) -> Response {
    // Check if admin is authenticated
    if private_cookies.get("admin_session").is_none() {
        return Redirect::to("/admin/login").into_response();
    }

    let lang = language(&cookies, &headers);
    rust_i18n::set_locale(lang.to_locale());

    // Get pre-filled UUID from query params
    let prefilled_uuid = params.get("uuid").unwrap_or(&String::new()).clone();

    let markup = Page::new(lang).content(html! {
        h1 { "Add Camera" }
        @if !prefilled_uuid.is_empty() {
            p.text-muted { "Auto-detected missing camera with UUID: " strong { (prefilled_uuid) } }
        }
        form method="POST" action="/admin/cameras/add" {
            fieldset {
                label for="uuid" { "Camera UUID:" }
                input
                    type="text"
                    name="uuid"
                    id="uuid"
                    placeholder="e.g., 123e4567-e89b-12d3-a456-426614174000"
                    value=(prefilled_uuid)
                    required;

                label for="name" { "Camera Name:" }
                input
                    type="text"
                    name="name"
                    id="name"
                    placeholder="e.g., Front Entrance Camera"
                    required;

                label for="desc" { "Description (optional):" }
                textarea
                    name="desc"
                    id="desc"
                    placeholder="e.g., Camera monitoring the main entrance" {};

                input type="submit" value="Add Camera";
            }
        }
        p {
            a href="/protected" { "← Back to Admin Dashboard" }
        }
    });

    markup.into_response()
}

async fn manage_cameras_page(
    State(state): State<AppState>,
    private_cookies: PrivateCookieJar,
    cookies: CookieJar,
    headers: HeaderMap,
) -> Response {
    // Check if admin is authenticated
    if private_cookies.get("admin_session").is_none() {
        return Redirect::to("/admin/login").into_response();
    }

    let lang = language(&cookies, &headers);
    rust_i18n::set_locale(lang.to_locale());

    let cameras = state.backend.get_all_cameras().await;

    let markup = Page::new(lang).content(html! {
        h1 { "Manage Cameras" }
        p { "Total cameras: " strong { (cameras.len()) } }
        
        @if cameras.is_empty() {
            p.text-muted { "No cameras found in the system." }
        } @else {
            table {
                thead {
                    tr {
                        th { "UUID" }
                        th { "Name" }
                        th { "Description" }
                        th { "Actions" }
                    }
                }
                tbody {
                    @for camera in &cameras {
                        tr {
                            td { 
                                code { (camera.uuid) }
                            }
                            td { (camera.name) }
                            td { 
                                @if let Some(desc) = &camera.desc {
                                    (desc)
                                } @else {
                                    em.text-muted { "No description" }
                                }
                            }
                            td {
                                a href=(format!("/admin/cameras/{}/edit", camera.uuid)) class="secondary" style="margin-right: 0.5rem;" { "Edit" }
                                form method="POST" action="/admin/cameras/delete" style="display: inline;" {
                                    input type="hidden" name="uuid" value=(camera.uuid);
                                    input 
                                        type="submit" 
                                        value="Delete" 
                                        class="secondary"
                                        onclick="return confirm('Are you sure you want to delete this camera? This will also remove all associated sightings.')";
                                }
                            }
                        }
                    }
                }
            }
        }
        
        p {
            a href="/admin/cameras/add" { "Add New Camera" }
            " | "
            a href="/protected" { "← Back to Admin Dashboard" }
        }
    });

    markup.into_response()
}

async fn add_camera(
    State(state): State<AppState>,
    private_cookies: PrivateCookieJar,
    Form(form): Form<CameraForm>,
) -> Response {
    // Check if admin is authenticated
    if private_cookies.get("admin_session").is_none() {
        return Redirect::to("/admin/login").into_response();
    }

    // Parse UUID
    let uuid = match Uuid::parse_str(&form.uuid) {
        Ok(uuid) => uuid,
        Err(_) => return Redirect::to("/admin/cameras/add?error=invalid_uuid").into_response(),
    };

    // Check if camera already exists
    if state.backend.get_camera(&uuid).await.is_some() {
        return Redirect::to("/admin/cameras/add?error=already_exists").into_response();
    }

    // Create the camera
    let desc = if form
        .desc
        .as_ref()
        .map(|s| s.trim().is_empty())
        .unwrap_or(true)
    {
        None
    } else {
        form.desc.as_deref()
    };

    match state.backend.create_camera(&uuid, &form.name, desc).await {
        Ok(_) => Redirect::to("/admin/cameras?camera_added=1").into_response(),
        Err(_) => Redirect::to("/admin/cameras/add?error=creation_failed").into_response(),
    }
}

async fn edit_camera_page(
    State(state): State<AppState>,
    private_cookies: PrivateCookieJar,
    cookies: CookieJar,
    headers: HeaderMap,
    Path(uuid_str): Path<String>,
) -> Response {
    // Check if admin is authenticated
    if private_cookies.get("admin_session").is_none() {
        return Redirect::to("/admin/login").into_response();
    }

    let lang = language(&cookies, &headers);
    rust_i18n::set_locale(lang.to_locale());

    // Parse UUID
    let uuid = match Uuid::parse_str(&uuid_str) {
        Ok(uuid) => uuid,
        Err(_) => return Redirect::to("/admin/cameras?error=invalid_uuid").into_response(),
    };

    // Get camera details
    let Some(camera) = state.backend.get_camera(&uuid).await else {
        return Redirect::to("/admin/cameras?error=not_found").into_response();
    };

    let markup = Page::new(lang).content(html! {
        h1 { "Edit Camera" }
        p.text-muted { "UUID: " code { (camera.uuid) } }
        
        form method="POST" action=(format!("/admin/cameras/{}/edit", camera.uuid)) {
            fieldset {
                label for="name" { "Camera Name:" }
                input
                    type="text"
                    name="name"
                    id="name"
                    value=(camera.name)
                    required;

                label for="desc" { "Description (optional):" }
                textarea
                    name="desc"
                    id="desc"
                    placeholder="e.g., Camera monitoring the main entrance" {
                        @if let Some(desc) = &camera.desc {
                            (desc)
                        }
                    }

                input type="submit" value="Update Camera";
            }
        }
        p {
            a href="/admin/cameras" { "← Back to Camera List" }
        }
    });

    markup.into_response()
}

async fn update_camera(
    State(state): State<AppState>,
    private_cookies: PrivateCookieJar,
    Path(uuid_str): Path<String>,
    Form(form): Form<EditCameraForm>,
) -> Response {
    // Check if admin is authenticated
    if private_cookies.get("admin_session").is_none() {
        return Redirect::to("/admin/login").into_response();
    }

    // Parse UUID
    let uuid = match Uuid::parse_str(&uuid_str) {
        Ok(uuid) => uuid,
        Err(_) => return Redirect::to("/admin/cameras?error=invalid_uuid").into_response(),
    };

    // Process description
    let desc = if form
        .desc
        .as_ref()
        .map(|s| s.trim().is_empty())
        .unwrap_or(true)
    {
        None
    } else {
        form.desc.as_deref()
    };

    match state.backend.update_camera(&uuid, &form.name, desc).await {
        Ok(true) => Redirect::to("/admin/cameras?camera_updated=1").into_response(),
        Ok(false) => Redirect::to("/admin/cameras?error=not_found").into_response(),
        Err(_) => Redirect::to("/admin/cameras?error=update_failed").into_response(),
    }
}

async fn delete_camera(
    State(state): State<AppState>,
    private_cookies: PrivateCookieJar,
    Form(form): Form<DeleteCameraForm>,
) -> Response {
    // Check if admin is authenticated
    if private_cookies.get("admin_session").is_none() {
        return Redirect::to("/admin/login").into_response();
    }

    // Parse UUID
    let uuid = match Uuid::parse_str(&form.uuid) {
        Ok(uuid) => uuid,
        Err(_) => return Redirect::to("/admin/cameras?error=invalid_uuid").into_response(),
    };

    match state.backend.delete_camera(&uuid).await {
        Ok(true) => Redirect::to("/admin/cameras?camera_deleted=1").into_response(),
        Ok(false) => Redirect::to("/admin/cameras?error=not_found").into_response(),
        Err(_) => Redirect::to("/admin/cameras?error=deletion_failed").into_response(),
    }
}

pub fn routes() -> Router<AppState> {
    Router::new()
        .route("/admin/login", get(login_page))
        .route("/admin/login", post(login))
        .route("/admin/logout", post(logout))
        .route("/protected", get(protected_page))
        .route("/admin/cameras", get(manage_cameras_page))
        .route("/admin/cameras/add", get(add_camera_page))
        .route("/admin/cameras/add", post(add_camera))
        .route("/admin/cameras/{uuid}/edit", get(edit_camera_page))
        .route("/admin/cameras/{uuid}/edit", post(update_camera))
        .route("/admin/cameras/delete", post(delete_camera))
}
