import * as anchor from "@coral-xyz/anchor";
import { Program, AnchorProvider, Wallet } from "@coral-xyz/anchor";
import { PublicKey, Keypair, Connection } from "@solana/web3.js";
import { createMint } from "@solana/spl-token";
import { setTestContext, getDbConfig } from "./setup";
import { DbTestHelper } from "./db_helper";
import * as fs from "fs";
import * as path from "path";

describe("EU ETS Web3 - Complete System Test (API)", () => {
  const rpcUrl = "http://127.0.0.1:8899";
  const programIdStr = "ACebqkxGWfinRtBEEwUXVipt9A5A7WVtH14vXN8AXDr4";
  const axumBaseUrl = "http://0.0.0.0:3001";

  const connection = new Connection(rpcUrl);
  const programId = new PublicKey(programIdStr);

  // Load IDL
  const idlPath = path.join(__dirname, "../../blockchain/eu_ets_web3/target/idl/eu_ets_web3.json");
  const idl = JSON.parse(fs.readFileSync(idlPath, "utf8"));

  // Create a dummy wallet for provider
  const dummyWallet = new Wallet(Keypair.generate());
  const provider = new AnchorProvider(connection, dummyWallet, {
    commitment: "finalized",
  });

  const program = new Program(idl, provider);

  // Authority keypairs
  let programAuthority: Keypair;
  let globalAdmin: Keypair;
  let localAdminGermany: Keypair;
  let localAdminFrance: Keypair;
  let company1Admin: Keypair;
  let company2Admin: Keypair;

  // PDAs
  let registryPda: PublicKey;
  let localAdminGermanyPda: PublicKey;
  let localAdminFrancePda: PublicKey;
  let company1Pda: PublicKey;
  let company2Pda: PublicKey;
  let marketPda: PublicKey;

  // Token mint
  let usdcMint: PublicKey;

  // Database helper
  let db: DbTestHelper;

  before(async () => {
    // Initialize database connection
    const dbConfig = getDbConfig();
    db = new DbTestHelper(dbConfig);
    console.log("✓ Database connection established");

    // Generate keypairs
    const PROGRAM_AUTHORITY_SECRET_KEY_BYTES = new Uint8Array([
      140, 111, 122, 186, 33, 37, 155, 97, 124, 53, 180, 208, 90, 206, 78, 172, 35, 227, 130, 240,
      178, 225, 48, 90, 130, 99, 47, 247, 7, 101, 144, 14, 197, 61, 72, 212, 28, 25, 110, 117, 46,
      162, 15, 199, 235, 58, 62, 204, 174, 47, 38, 36, 191, 68, 215, 99, 175, 132, 233, 97, 143, 168,
      38, 7,
    ]);
    programAuthority = Keypair.fromSecretKey(PROGRAM_AUTHORITY_SECRET_KEY_BYTES);

    globalAdmin = Keypair.generate();
    localAdminGermany = Keypair.generate();
    localAdminFrance = Keypair.generate();
    company1Admin = Keypair.generate();
    company2Admin = Keypair.generate();

    // Airdrop SOL
    const airdropAmount = 10 * anchor.web3.LAMPORTS_PER_SOL;
    const accounts = [
      programAuthority,
      globalAdmin,
      localAdminGermany,
      localAdminFrance,
      company1Admin,
      company2Admin,
    ];

    for (const account of accounts) {
      console.log("airdropping " + airdropAmount + " sol to " + account.publicKey);
      await connection.confirmTransaction(
        await connection.requestAirdrop(account.publicKey, airdropAmount)
      );
    }

    // Create mock USDC mint (6 decimals like real USDC)
    usdcMint = await createMint(
      connection,
      globalAdmin,
      globalAdmin.publicKey,
      null,
      6
    );
    console.log("Mock USDC mint created:", usdcMint.toBase58());

    // Find PDAs
    [registryPda] = PublicKey.findProgramAddressSync(
      [Buffer.from("registry")],
      programId
    );

    [localAdminGermanyPda] = PublicKey.findProgramAddressSync(
      [Buffer.from("local_admin"), localAdminGermany.publicKey.toBuffer()],
      programId
    );

    [localAdminFrancePda] = PublicKey.findProgramAddressSync(
      [Buffer.from("local_admin"), localAdminFrance.publicKey.toBuffer()],
      programId
    );

    [company1Pda] = PublicKey.findProgramAddressSync(
      [Buffer.from("company"), company1Admin.publicKey.toBuffer()],
      programId
    );

    [company2Pda] = PublicKey.findProgramAddressSync(
      [Buffer.from("company"), company2Admin.publicKey.toBuffer()],
      programId
    );

    [marketPda] = PublicKey.findProgramAddressSync(
      [Buffer.from("market")],
      programId
    );

    // Store everything in shared context
    setTestContext({
      connection,
      program,
      axumBaseUrl,
      programAuthority,
      globalAdmin,
      localAdminGermany,
      localAdminFrance,
      company1Admin,
      company2Admin,
      registryPda,
      localAdminGermanyPda,
      localAdminFrancePda,
      company1Pda,
      company2Pda,
      marketPda,
      usdcMint,
      db,
    });
  });

  after(async () => {
    // Close database connection
    if (db) {
      await db.close();
      console.log("✓ Database connection closed");
    }
  });

  // Import test suites in correct order
  require("./registry/initialize_registry.test");
  require("./registry/register_local_admins.test");
  require("./registry/register_companies.test");
  require("./registry/allocate_eua.test");

  require("./secondary_market/initialize_market.test");
  require("./secondary_market/deposit_usdc.test");
  require("./secondary_market/place_cancel_order.test.ts")
  require("./secondary_market/withdraw_usdc.test.ts")

  require("./primary_market/initialize_primary_market.test");
  require("./primary_market/initialize_vk.test");
  require("./primary_market/publish_auction.test");
  require("./primary_market/start_auction.test");
  // require("./primary_market/join_auction.test");
  // require("./primary_market/place_bid.test");
});
