// 库存管理模块
use serde::Deserialize;
use crate::models::*;
use crate::database::DB_CONN;
use crate::operation_logs::log_operation;
use crate::error_util;
use crate::permissions::check_permission;
use uuid::Uuid;
use chrono::Local;

#[derive(Debug, Deserialize)]
pub struct AdjustInventoryRequest {
    pub product_id: String,
    pub product_name: String,
    pub new_stock: f64,
    pub new_stock_unit2: f64,
    pub remark: String,
}

#[tauri::command]
pub fn get_inventory() -> Result<Vec<Product>, String> {
    let conn_guard = DB_CONN.lock().map_err(|e| e.to_string())?;
    let conn = conn_guard.as_ref().ok_or("Database not initialized")?;
    
    let mut stmt = conn.prepare(
        "SELECT id, name, code, category, unit, unit2, price, cost, stock, stock_unit2, \
         batch_no, production_date, expiry_date, brand, model, package_type, description, image_path, \
         warehouse_id, location_id, created_at, barcode, trace_code, status, category_id, unit_rate \
         FROM products ORDER BY name"
    ).map_err(|e| e.to_string())?;
    let products = stmt.query_map([], |row| {
        Ok(Product {
            id: row.get::<_, String>(0).unwrap_or_default(),
            name: row.get::<_, String>(1).unwrap_or_default(),
            code: row.get::<_, String>(2).unwrap_or_default(),
            category: row.get::<_, Option<String>>(3)?.unwrap_or_default(),
            unit: row.get::<_, String>(4).unwrap_or_default(),
            unit2: row.get::<_, Option<String>>(5)?.unwrap_or_default(),
            price: row.get::<_, f64>(6).unwrap_or(0.0),
            cost: row.get::<_, f64>(7).unwrap_or(0.0),
            stock: row.get::<_, f64>(8).unwrap_or(0.0),
            stock_unit2: row.get::<_, Option<f64>>(9)?.unwrap_or(0.0),
            batch_no: row.get::<_, Option<String>>(10)?.unwrap_or_default(),
            production_date: row.get::<_, Option<String>>(11)?.unwrap_or_default(),
            expiry_date: row.get::<_, Option<String>>(12)?.unwrap_or_default(),
            brand: row.get::<_, Option<String>>(13)?.unwrap_or_default(),
            model: row.get::<_, Option<String>>(14)?.unwrap_or_default(),
            package_type: row.get::<_, Option<String>>(15)?.unwrap_or_default(),
            description: row.get::<_, Option<String>>(16)?.unwrap_or_default(),
            image_path: row.get::<_, Option<String>>(17)?.unwrap_or_default(),
            warehouse_id: row.get::<_, Option<String>>(18)?.unwrap_or_default(),
            location_id: row.get::<_, Option<String>>(19)?.unwrap_or_default(),
            barcode: row.get::<_, Option<String>>(21)?.unwrap_or_default(),
            trace_code: row.get::<_, Option<String>>(22)?.unwrap_or_default(),
            status: row.get::<_, Option<String>>(23)?.unwrap_or_default(),
            category_id: row.get::<_, Option<String>>(24)?.unwrap_or_default(),
            unit_rate: row.get::<_, Option<f64>>(25)?.unwrap_or(1.0),
            created_at: row.get::<_, String>(20).unwrap_or_default(),
        })
    }).map_err(|e| e.to_string())?;
    
    products.collect::<Result<Vec<_>, _>>().map_err(|e| e.to_string())
}

#[tauri::command]
pub fn get_inventory_records() -> Result<Vec<InventoryRecord>, String> {
    let conn_guard = DB_CONN.lock().map_err(|e| e.to_string())?;
    let conn = conn_guard.as_ref().ok_or("Database not initialized")?;
    
    let mut stmt = conn.prepare(
        "SELECT ir.id, ir.product_id, ir.product_name, COALESCE(p.code,'') as product_code, 
         CASE ir.change_type 
           WHEN 'return_in' THEN 'sale_return' 
           WHEN 'return_out' THEN 'purchase_return' 
           ELSE ir.change_type 
         END as change_type,
         ir.quantity, ir.before_stock, ir.after_stock, ir.remark, ir.created_at
         FROM inventory_records ir 
         LEFT JOIN products p ON ir.product_id = p.id 
         ORDER BY ir.created_at DESC LIMIT 100"
    ).map_err(|e| e.to_string())?;
    let records = stmt.query_map([], |row| {
        Ok(InventoryRecord {
            id: row.get(0)?,
            product_id: row.get(1)?,
            product_name: row.get(2)?,
            product_code: row.get::<_, String>(3).unwrap_or_default(),
            change_type: row.get(4)?,
            quantity: row.get(5)?,
            before_stock: row.get(6)?,
            after_stock: row.get(7)?,
            remark: row.get(8)?,
            created_at: row.get(9)?,
        })
    }).map_err(|e| e.to_string())?;
    
    records.collect::<Result<Vec<_>, _>>().map_err(|e| e.to_string())
}

#[tauri::command]
pub fn adjust_inventory(request: AdjustInventoryRequest, username: String, real_name: String) -> Result<Product, String> {
    if !check_permission(&username, "inventory_ops") {
        return Err("权限不足：没有调整库存的权限".to_string());
    }
    let mut conn_guard = DB_CONN.lock().map_err(|e| error_util::to_chinese_error(e))?;
    let conn = conn_guard.as_mut().ok_or("系统错误：数据库未初始化")?;

    let tx = conn.transaction().map_err(|e| error_util::to_chinese_error(e))?;

    let current_stock: f64 = tx.query_row(
        "SELECT stock FROM products WHERE id = ?1",
        [&request.product_id], |row| row.get(0)
    ).map_err(|e| error_util::to_chinese_error(e))?;

    let change = request.new_stock - current_stock;
    let _change2 = request.new_stock_unit2 - 0.0;

    tx.execute(
        "UPDATE products SET stock=?1, stock_unit2=?2 WHERE id=?3",
        [&request.new_stock.to_string(), &request.new_stock_unit2.to_string(), &request.product_id]
    ).map_err(|e| error_util::to_chinese_error(e))?;

    let now = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();

    if change.abs() > 0.0001 {
        let change_type = if change >= 0.0 { "adjust_in" } else { "adjust_out" };
        tx.execute(
            "INSERT INTO inventory_records (id, product_id, product_name, change_type, quantity, before_stock, after_stock, remark, created_at) 
             VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)",
            [&Uuid::new_v4().to_string(), &request.product_id, &request.product_name,
             change_type, &change.to_string(), &current_stock.to_string(), &request.new_stock.to_string(),
             &request.remark, &now]
        ).map_err(|e| error_util::to_chinese_error(e))?;
    }

    let product: Product = tx.query_row(
        "SELECT * FROM products WHERE id=?1",
        [&request.product_id], |row| {
            Ok(Product {
                id: row.get(0)?, name: row.get(1)?, code: row.get(2)?, category: row.get(3)?,
                unit: row.get(4)?, unit2: row.get::<_, Option<String>>(5)?.unwrap_or_default(),
                price: row.get(6)?, cost: row.get(7)?, stock: row.get(8)?,
                stock_unit2: row.get::<_, Option<f64>>(9)?.unwrap_or(0.0),
                batch_no: row.get::<_, Option<String>>(10)?.unwrap_or_default(),
                production_date: row.get::<_, Option<String>>(11)?.unwrap_or_default(),
                expiry_date: row.get::<_, Option<String>>(12)?.unwrap_or_default(),
                brand: row.get::<_, Option<String>>(13)?.unwrap_or_default(),
                model: row.get::<_, Option<String>>(14)?.unwrap_or_default(),
                package_type: row.get::<_, Option<String>>(15)?.unwrap_or_default(),
                description: row.get::<_, Option<String>>(16)?.unwrap_or_default(),
                image_path: row.get::<_, Option<String>>(17)?.unwrap_or_default(),
                warehouse_id: row.get::<_, Option<String>>(18)?.unwrap_or_default(),
                location_id: row.get::<_, Option<String>>(19)?.unwrap_or_default(),
                barcode: row.get::<_, Option<String>>(21).unwrap_or(None).unwrap_or_default(),
                trace_code: row.get::<_, Option<String>>(22).unwrap_or(None).unwrap_or_default(),
                status: row.get::<_, Option<String>>(23).unwrap_or(None).unwrap_or_default(),
                category_id: row.get::<_, Option<String>>(24).unwrap_or(None).unwrap_or_default(),
                unit_rate: row.get::<_, Option<f64>>(25)?.unwrap_or(1.0),
                created_at: row.get::<_, String>(20).unwrap_or_default(),
            })
        }
    ).map_err(|e| error_util::to_chinese_error(e))?;

    tx.commit().map_err(|e| error_util::to_chinese_error(e))?;
    
    log_operation(&username, &real_name, "调整库存", "库存管理", &format!("商品{} 调整至{}", request.product_name, request.new_stock));
    
    Ok(product)
}

#[tauri::command]
pub fn get_warehouse_stock() -> Result<Vec<serde_json::Value>, String> {
    let conn_guard = DB_CONN.lock().map_err(|e| e.to_string())?;
    let conn = conn_guard.as_ref().ok_or("系统错误：数据库未初始化")?;
    
    let mut stmt = conn.prepare(
        "SELECT ws.product_id, p.name as product_name, p.code as product_code, ws.warehouse_id, w.name as warehouse_name, ws.stock 
         FROM warehouse_stock ws 
         JOIN products p ON ws.product_id = p.id 
         JOIN warehouses w ON ws.warehouse_id = w.id 
         ORDER BY w.name, p.name"
    ).map_err(|e| e.to_string())?;
    
    let rows = stmt.query_map([], |row| {
        Ok(serde_json::json!({
            "product_id": row.get::<_, String>(0)?,
            "product_name": row.get::<_, String>(1)?,
            "product_code": row.get::<_, String>(2)?,
            "warehouse_id": row.get::<_, String>(3)?,
            "warehouse_name": row.get::<_, String>(4)?,
            "stock": row.get::<_, f64>(5)?,
        }))
    }).map_err(|e| e.to_string())?;
    
    let mut result = Vec::new();
    for r in rows { result.push(r.map_err(|e| e.to_string())?); }
    Ok(result)
}