use base64::{engine::general_purpose::STANDARD, Engine as _};
use ed25519_dalek::{Signer, SigningKey};
use serde::{Deserialize, Serialize};
use std::env;
use std::fs;
use std::io::{Read, Write};
use std::net::TcpListener;
use std::path::PathBuf;

#[derive(Serialize, Deserialize)]
struct LicensePayload {
  product_id: String,
  license_key: String,
  hwid: String,
}

fn find_workspace_root() -> PathBuf {
  let mut dir = env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
  loop {
    if dir.join("licensing_profiles.json").exists() || dir.join("src-tauri").exists() {
      return dir;
    }
    if let Some(parent) = dir.parent() {
      dir = parent.to_path_buf();
    } else {
      break;
    }
  }

  env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
}

fn main() -> Result<(), String> {
  ctrlc::set_handler(move || {
    println!("\n[Mock License Server] Shutting down gracefully. Releasing port 3000.");
    std::process::exit(0);
  })
  .map_err(|e| format!("Error setting Ctrl-C handler: {}", e))?;

  let listener = TcpListener::bind("127.0.0.1:3000")
    .map_err(|e| format!("Failed to bind to port 3000: {}", e))?;

  println!("[Mock License Server] Listening on http://localhost:3000");
  println!("[Mock License Server] Press Ctrl+C to stop.");

  let workspace_root = find_workspace_root();
  let dev_priv_path = workspace_root.join("licensing").join("development.priv");

  let priv_key_hex = fs::read_to_string(&dev_priv_path)
    .map_err(|e| format!(
      "Failed to read development private key from {}: {}.\nMake sure you have run 'cargo run --bin license_tool generate-keys development' first.", 
      dev_priv_path.display(), e
    ))?;

  let priv_key_hex = priv_key_hex.trim();

  let mut priv_key_bytes = Vec::new();
  let mut chars = priv_key_hex.chars().peekable();

  while chars.peek().is_some() {
    let chunk: String = chars.by_ref().take(2).collect();
    let byte = u8::from_str_radix(&chunk, 16)
      .map_err(|e| format!("Invalid hex byte in private key: {}", e))?;

    priv_key_bytes.push(byte);
  }

  let priv_key_arr: [u8; 32] = priv_key_bytes
    .try_into()
    .map_err(|_| "Private key must be exactly 32 bytes (64 hex characters)".to_string())?;

  let signing_key = SigningKey::from_bytes(&priv_key_arr);
  println!("[Mock License Server] Successfully loaded development private key from disk.");

  for stream in listener.incoming() {
    let mut stream = match stream {
      Ok(s) => s,
      Err(e) => {
        println!("[Mock License Server] Connection failed: {}", e);
        continue;
      }
    };

    let mut request_bytes = Vec::new();
    let mut temp_buffer = [0u8; 1024];
    let mut body_start_idx = None;
    let mut content_length = None;

    loop {
      let n = match stream.read(&mut temp_buffer) {
        Ok(0) => break, // Connection closed
        Ok(n) => n,
        Err(e) => {
          println!("[Mock License Server] Read error: {}", e);
          break;
        }
      };

      request_bytes.extend_from_slice(&temp_buffer[..n]);

      let req_str = String::from_utf8_lossy(&request_bytes);

      if let Some(idx) = req_str.find("\r\n\r\n") {
        body_start_idx = Some(idx + 4);

        for line in req_str[..idx].lines() {
          if line.to_lowercase().starts_with("content-length:") {
            if let Some(val_str) = line.split(':').nth(1) {
              if let Ok(len) = val_str.trim().parse::<usize>() {
                content_length = Some(len);
              }
            }
          }
        }
        break;
      }
    }

    if let (Some(start), Some(len)) = (body_start_idx, content_length) {
      while request_bytes.len() < start + len {
        let n = match stream.read(&mut temp_buffer) {
          Ok(0) => break,
          Ok(n) => n,
          Err(e) => {
            println!("[Mock License Server] Read body error: {}", e);
            break;
          }
        };

        request_bytes.extend_from_slice(&temp_buffer[..n]);
      }

      let req_str = String::from_utf8_lossy(&request_bytes);
      let body = &req_str[start..start + len];

      #[derive(Deserialize)]
      struct ActivationRequest {
        product_id: String,
        license_key: String,
        hwid: String,
      }

      if let Ok(req_data) = serde_json::from_str::<ActivationRequest>(body.trim()) {
        if req_data.license_key.starts_with("pi_invalid") {
          let response_body = serde_json::json!({
            "error": "Activation failed: Invalid Stripe Mock Payment ID."
          })
          .to_string();

          let response = format!(
            "HTTP/1.1 400 Bad Request\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
            response_body.len(),
            response_body
          );

          let _ = stream.write_all(response.as_bytes());

          println!(
            "[Mock License Server] Rejected key '{}' for product '{}' on machine '{}'",
            req_data.license_key, req_data.product_id, req_data.hwid
          );
        } else {
          let payload = LicensePayload {
            product_id: req_data.product_id,
            license_key: req_data.license_key.clone(),
            hwid: req_data.hwid.clone(),
          };

          let payload_str = serde_json::to_string(&payload).unwrap();
          let payload_b64 = STANDARD.encode(payload_str.as_bytes());

          let signature = signing_key.sign(payload_b64.as_bytes());
          let signature_b64 = STANDARD.encode(signature.to_bytes());

          let token = format!("{}.{}", payload_b64, signature_b64);
          let response_body = serde_json::json!({
            "license_token": token
          })
          .to_string();

          let response = format!(
            "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
            response_body.len(),
            response_body
          );

          let _ = stream.write_all(response.as_bytes());

          println!(
            "[Mock License Server] Successfully activated license for product '{}' on machine '{}'",
            payload.product_id, payload.hwid
          );
        }
      } else {
        let response_body = serde_json::json!({
          "error": "Invalid request payload format."
        })
        .to_string();

        let response = format!(
          "HTTP/1.1 400 Bad Request\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
          response_body.len(),
          response_body
        );

        let _ = stream.write_all(response.as_bytes());

        println!(
          "[Mock License Server] Failed parsing request JSON payload body: '{}'",
          body
        );
      }
    } else {
      let response = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\nConnection: close\r\n\r\n";

      let _ = stream.write_all(response.as_bytes());

      println!("[Mock License Server] Invalid HTTP request headers or missing Content-Length");
    }
  }

  Ok(())
}
