import * as anchor from "@coral-xyz/anchor";
import { SystemProgram, Transaction } from "@solana/web3.js";
import { expect } from "chai";
import fetch from "node-fetch";
import { getTestContext } from "../setup";

describe("Publish Auction (API)", () => {
  it("Local Admin Germany Publishes Auction with 1000 EUA", async () => {
    const ctx = getTestContext();
    const {
      connection,
      program,
      axumBaseUrl,
      localAdminGermany,
      localAdminGermanyPda,
      localAdminGermanyEuaVault
    } = ctx;

    // Derive primary market PDA
    const [primaryMarketPda] = anchor.web3.PublicKey.findProgramAddressSync(
      [Buffer.from("primary_market")],
      program.programId
    );

    // Set auction times: start in 5 seconds, close in 1 hour
    const currentTime = Math.floor(Date.now() / 1000);
    const startTime = currentTime + 5;
    const closeTime = startTime + 3600;

    // Step 1: Create API request payload (NO auction PDA - backend will calculate it)
    const request = {
      primary_market: primaryMarketPda.toBase58(),
      local_admin: localAdminGermanyPda.toBase58(),
      local_admin_eua_vault: localAdminGermanyEuaVault.toBase58(),
      local_admin_pubkey: localAdminGermany.publicKey.toBase58(),
      eua_volume: 1000, // Must be divisible by 500
      start_time: startTime,
      close_time: closeTime,
    };

    console.log("Calling API to create publish auction transaction...");
    console.log("Note: Backend will calculate the auction PDA using on-chain total_auctions");

    // Step 2: Call Axum API to get unsigned transaction
    const createTxResponse = await fetch(
      `${axumBaseUrl}/api/primary-market/publish-auction`,
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(request),
      }
    );

    if (!createTxResponse.ok) {
      const error = await createTxResponse.text();
      throw new Error(`Failed to create transaction: ${error}`);
    }

    const { transaction_base64, message, auction_pda } = await createTxResponse.json();
    console.log(`API Response: ${message}`);
    console.log(`Auction PDA (calculated by backend): ${auction_pda}`);

    const auctionPda = new anchor.web3.PublicKey(auction_pda);

    // Step 3: Deserialize and sign transaction
    const txBuffer = Buffer.from(transaction_base64, "base64");
    const transaction = Transaction.from(txBuffer);

    console.log("Transaction signer (expected):");
    console.log("  Local Admin Germany:", localAdminGermany.publicKey.toBase58());

    // Sign with localAdminGermany (the only required signer)
    transaction.sign(localAdminGermany);

    console.log("Transaction signed locally");

    // Step 4: Submit signed transaction to backend
    const signedTxBase64 = transaction.serialize().toString("base64");
    const submitTxResponse = await fetch(`${axumBaseUrl}/api/submit-tx`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ transaction_base64: signedTxBase64 }),
    });

    if (!submitTxResponse.ok) {
      const error = await submitTxResponse.text();
      throw new Error(`Failed to submit transaction: ${error}`);
    }

    const { signature } = await submitTxResponse.json();
    console.log(`✓ Transaction signature: ${signature}`);

    // Step 5: Verify on-chain state - AUCTION CREATED
    const auction = await program.account.auction.fetch(auctionPda);

    expect(auction.localAdmin.equals(localAdminGermanyPda)).to.be.true;
    expect(auction.euaVolumeOffered.toNumber()).to.equal(1000);
    expect(auction.startTime.toNumber()).to.equal(startTime);
    expect(auction.closeTime.toNumber()).to.equal(closeTime);
    expect(auction.status).to.deep.equal({ published: {} });
    expect(auction.totalBids).to.equal(0);

    console.log("✓ Auction account state verified");
    console.log(`  - Auction ID: ${auction.auctionId.toNumber()}`);
    console.log(`  - EUA Volume Offered: ${auction.euaVolumeOffered.toNumber()}`);
    console.log(`  - Lot Size: ${auction.lotSize}`);
    console.log(`  - Start Time: ${new Date(startTime * 1000).toISOString()}`);
    console.log(`  - Close Time: ${new Date(closeTime * 1000).toISOString()}`);
    console.log(`  - Status: Published`);
    console.log(`  - Total Bids: ${auction.totalBids}`);

    // Step 6: Verify local admin state updated
    const localAdmin = await program.account.localAdmin.fetch(localAdminGermanyPda);

    expect(localAdmin.activeAuction).to.not.be.null;
    expect(localAdmin.activeAuction.equals(auctionPda)).to.be.true;

    console.log(`✓ Local Admin updated:`);
    console.log(`  - Active Auction: ${localAdmin.activeAuction.toBase58()}`);
    console.log(`  - Total Auctions: ${localAdmin.totalAuctions.toNumber()}`);

    // Step 7: Verify events/logs
    const txDetails = await connection.getTransaction(signature, {
      commitment: "confirmed",
      maxSupportedTransactionVersion: 0,
    });

    if (txDetails?.meta?.logMessages) {
      const logs = txDetails.meta.logMessages;

      const hasPublishLog = logs.some((log) =>
        log.includes("Auction published") || log.includes("AuctionPublished")
      );

      if (hasPublishLog) {
        console.log("✓ Auction published event found in logs");
      }
    }

    console.log("✓ Auction published successfully via API");

    // Store auction PDA for subsequent tests
    const { setTestContext } = require("../setup");
    setTestContext({
      auctionPda,
      auctionId: auction.auctionId.toNumber(),
    });
  });


  // it("Should Reject Publishing Auction with Invalid EUA Volume", async () => {
  //   const ctx = getTestContext();
  //   const {
  //     axumBaseUrl,
  //     localAdminGermany,
  //     localAdminGermanyPda,
  //     localAdminGermanyEuaVault,
  //   } = ctx;
  //
  //   const [primaryMarketPda] = anchor.web3.PublicKey.findProgramAddressSync(
  //     [Buffer.from("primary_market")],
  //     ctx.program.programId
  //   );
  //
  //   const currentTime = Math.floor(Date.now() / 1000);
  //
  //   const request = {
  //     primary_market: primaryMarketPda.toBase58(),
  //     local_admin: localAdminGermanyPda.toBase58(),
  //     local_admin_eua_vault: localAdminGermanyEuaVault.toBase58(),
  //     local_admin_pubkey: localAdminGermany.publicKey.toBase58(),
  //     eua_volume: 333, // Not divisible by 500
  //     start_time: currentTime + 5,
  //     close_time: currentTime + 3605,
  //   };
  //
  //   const createTxResponse = await fetch(
  //     `${axumBaseUrl}/api/primary-market/publish-auction`,
  //     {
  //       method: "POST",
  //       headers: { "Content-Type": "application/json" },
  //       body: JSON.stringify(request),
  //     }
  //   );
  //
  //   expect(createTxResponse.ok).to.be.false;
  //   const errorText = await createTxResponse.text();
  //   console.log("✓ Correctly rejected invalid EUA volume:", errorText);
  //   expect(errorText).to.include("divisible by 500");
  // });
  //
  // it("Should Reject Publishing Auction with Past Start Time", async () => {
  //   const ctx = getTestContext();
  //   const {
  //     axumBaseUrl,
  //     localAdminGermany,
  //     localAdminGermanyPda,
  //     localAdminGermanyEuaVault,
  //   } = ctx;
  //
  //   const [primaryMarketPda] = anchor.web3.PublicKey.findProgramAddressSync(
  //     [Buffer.from("primary_market")],
  //     ctx.program.programId
  //   );
  //
  //   const currentTime = Math.floor(Date.now() / 1000);
  //
  //   const request = {
  //     primary_market: primaryMarketPda.toBase58(),
  //     local_admin: localAdminGermanyPda.toBase58(),
  //     local_admin_eua_vault: localAdminGermanyEuaVault.toBase58(),
  //     local_admin_pubkey: localAdminGermany.publicKey.toBase58(),
  //     eua_volume: 1000,
  //     start_time: currentTime - 100, // Past time
  //     close_time: currentTime + 3600,
  //   };
  //
  //   const createTxResponse = await fetch(
  //     `${axumBaseUrl}/api/primary-market/publish-auction`,
  //     {
  //       method: "POST",
  //       headers: { "Content-Type": "application/json" },
  //       body: JSON.stringify(request),
  //     }
  //   );
  //
  //   expect(createTxResponse.ok).to.be.false;
  //   const errorText = await createTxResponse.text();
  //   console.log("✓ Correctly rejected past start time:", errorText);
  //   expect(errorText).to.include("future");
  // });
  //
  // it("Should Reject Publishing Auction When Local Admin Already Has Active Auction", async () => {
  //   const ctx = getTestContext();
  //   const {
  //     axumBaseUrl,
  //     localAdminGermany,
  //     localAdminGermanyPda,
  //     localAdminGermanyEuaVault,
  //   } = ctx;
  //
  //   const [primaryMarketPda] = anchor.web3.PublicKey.findProgramAddressSync(
  //     [Buffer.from("primary_market")],
  //     ctx.program.programId
  //   );
  //
  //   const currentTime = Math.floor(Date.now() / 1000);
  //
  //   const request = {
  //     primary_market: primaryMarketPda.toBase58(),
  //     local_admin: localAdminGermanyPda.toBase58(),
  //     local_admin_eua_vault: localAdminGermanyEuaVault.toBase58(),
  //     local_admin_pubkey: localAdminGermany.publicKey.toBase58(),
  //     eua_volume: 500,
  //     start_time: currentTime + 5,
  //     close_time: currentTime + 3605,
  //   };
  //
  //   const createTxResponse = await fetch(
  //     `${axumBaseUrl}/api/primary-market/publish-auction`,
  //     {
  //       method: "POST",
  //       headers: { "Content-Type": "application/json" },
  //       body: JSON.stringify(request),
  //     }
  //   );
  //
  //   expect(createTxResponse.ok).to.be.false;
  //   const errorText = await createTxResponse.text();
  //   console.log("✓ Correctly rejected duplicate active auction:", errorText);
  //   expect(errorText).to.include("active auction");
  // });
  //
  // it("Should Reject Publishing Auction with Insufficient Balance", async () => {
  //   const ctx = getTestContext();
  //   const {
  //     axumBaseUrl,
  //     localAdminGermany,
  //     localAdminGermanyPda,
  //     localAdminGermanyEuaVault,
  //   } = ctx;
  //
  //   const [primaryMarketPda] = anchor.web3.PublicKey.findProgramAddressSync(
  //     [Buffer.from("primary_market")],
  //     ctx.program.programId
  //   );
  //
  //   const currentTime = Math.floor(Date.now() / 1000);
  //
  //   const request = {
  //     primary_market: primaryMarketPda.toBase58(),
  //     local_admin: localAdminGermanyPda.toBase58(),
  //     local_admin_eua_vault: localAdminGermanyEuaVault.toBase58(),
  //     local_admin_pubkey: localAdminGermany.publicKey.toBase58(),
  //     eua_volume: 5000, // bigger than 3000 
  //     start_time: currentTime + 5,
  //     close_time: currentTime + 3605,
  //   };
  //
  //   const createTxResponse = await fetch(
  //     `${axumBaseUrl}/api/primary-market/publish-auction`,
  //     {
  //       method: "POST",
  //       headers: { "Content-Type": "application/json" },
  //       body: JSON.stringify(request),
  //     }
  //   );
  //
  //   expect(createTxResponse.ok).to.be.false;
  //   const errorText = await createTxResponse.text();
  //   console.log("✓ Correctly rejected insufficient balance:", errorText);
  //   expect(errorText).to.include("insufficient");
  // });

});
