package rest

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"time"
)

// handleEtherscanAPI handles GET /api?module=...&action=...
// This provides Etherscan-compatible API endpoints
func (s *Server) handleEtherscanAPI(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		writeMethodNotAllowed(w)
		return
	}
	if !s.requireDB(w) {
		return
	}

	module := r.URL.Query().Get("module")
	action := r.URL.Query().Get("action")

	// Etherscan-compatible response structure
	type EtherscanResponse struct {
		Status  string      `json:"status"`
		Message string      `json:"message"`
		Result  interface{} `json:"result"`
	}

	// Validate required parameters
	if module == "" || action == "" {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		response := EtherscanResponse{
			Status:  "0",
			Message: "Params 'module' and 'action' are required parameters",
			Result:  nil,
		}
		json.NewEncoder(w).Encode(response)
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	var response EtherscanResponse

	switch module {
	case "block":
		switch action {
		case "eth_block_number":
			// Get latest block number
			var blockNumber int64
			err := s.db.QueryRow(ctx,
				`SELECT MAX(number) FROM blocks WHERE chain_id = $1`,
				s.chainID,
			).Scan(&blockNumber)
			if err != nil {
				response = EtherscanResponse{
					Status:  "0",
					Message: "Error",
					Result:  "0x0",
				}
			} else {
				response = EtherscanResponse{
					Status:  "1",
					Message: "OK",
					Result:  fmt.Sprintf("0x%x", blockNumber),
				}
			}

		case "eth_get_block_by_number":
			tag := r.URL.Query().Get("tag")
			boolean := r.URL.Query().Get("boolean") == "true"

			// Parse block number from tag (can be "latest", "0x...", or decimal)
			var blockNumber int64
			if tag == "latest" {
				err := s.db.QueryRow(ctx,
					`SELECT MAX(number) FROM blocks WHERE chain_id = $1`,
					s.chainID,
				).Scan(&blockNumber)
				if err != nil {
					response = EtherscanResponse{
						Status:  "0",
						Message: "Error",
						Result:  nil,
					}
					break
				}
			} else if len(tag) > 2 && tag[:2] == "0x" {
				// Hex format
				parsed, err := strconv.ParseInt(tag[2:], 16, 64)
				if err != nil {
					response = EtherscanResponse{
						Status:  "0",
						Message: "Invalid block number",
						Result:  nil,
					}
					break
				}
				blockNumber = parsed
			} else {
				// Decimal format
				parsed, err := strconv.ParseInt(tag, 10, 64)
				if err != nil {
					response = EtherscanResponse{
						Status:  "0",
						Message: "Invalid block number",
						Result:  nil,
					}
					break
				}
				blockNumber = parsed
			}

			// Get block data
			var hash, parentHash, miner string
			var timestamp time.Time
			var transactionCount int
			var gasUsed, gasLimit int64
			var transactions []string

			query := `
				SELECT hash, parent_hash, timestamp, miner, transaction_count, gas_used, gas_limit
				FROM blocks
				WHERE chain_id = $1 AND number = $2
			`

			err := s.db.QueryRow(ctx, query, s.chainID, blockNumber).Scan(
				&hash, &parentHash, &timestamp, &miner, &transactionCount, &gasUsed, &gasLimit,
			)
			if err != nil {
				response = EtherscanResponse{
					Status:  "0",
					Message: "Block not found",
					Result:  nil,
				}
				break
			}

			// If boolean is true, get full transaction objects
			if boolean {
				txQuery := `
					SELECT hash FROM transactions
					WHERE chain_id = $1 AND block_number = $2
					ORDER BY transaction_index
				`
				rows, err := s.db.Query(ctx, txQuery, s.chainID, blockNumber)
				if err == nil {
					defer rows.Close()
					for rows.Next() {
						var txHash string
						if err := rows.Scan(&txHash); err == nil {
							transactions = append(transactions, txHash)
						}
					}
				}
			} else {
				// Just get transaction hashes
				txQuery := `
					SELECT hash FROM transactions
					WHERE chain_id = $1 AND block_number = $2
					ORDER BY transaction_index
				`
				rows, err := s.db.Query(ctx, txQuery, s.chainID, blockNumber)
				if err == nil {
					defer rows.Close()
					for rows.Next() {
						var txHash string
						if err := rows.Scan(&txHash); err == nil {
							transactions = append(transactions, txHash)
						}
					}
				}
			}

			blockResult := map[string]interface{}{
				"number":           fmt.Sprintf("0x%x", blockNumber),
				"hash":             hash,
				"parentHash":       parentHash,
				"timestamp":        fmt.Sprintf("0x%x", timestamp.Unix()),
				"miner":            miner,
				"transactions":     transactions,
				"transactionCount": fmt.Sprintf("0x%x", transactionCount),
				"gasUsed":          fmt.Sprintf("0x%x", gasUsed),
				"gasLimit":         fmt.Sprintf("0x%x", gasLimit),
			}

			response = EtherscanResponse{
				Status:  "1",
				Message: "OK",
				Result:  blockResult,
			}

		default:
			response = EtherscanResponse{
				Status:  "0",
				Message: "Invalid action",
				Result:  nil,
			}
		}

	default:
		response = EtherscanResponse{
			Status:  "0",
			Message: "Invalid module",
			Result:  nil,
		}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(response)
}

