package rest

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

// handleGetAddress handles GET /api/v1/addresses/{chain_id}/{address}
func (s *Server) handleGetAddress(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		writeMethodNotAllowed(w)
		return
	}
	if !s.requireDB(w) {
		return
	}

	// Parse address from URL
	address := normalizeAddress(r.URL.Query().Get("address"))
	if address == "" {
		writeValidationError(w, fmt.Errorf("address required"))
		return
	}

	// Validate address format
	if !isValidAddress(address) {
		writeValidationError(w, ErrInvalidAddress)
		return
	}

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

	// Get transaction count
	var txCount int64
	err := s.db.QueryRow(ctx,
		`SELECT COUNT(*) FROM transactions WHERE chain_id = $1 AND (LOWER(from_address) = $2 OR LOWER(to_address) = $2)`,
		s.chainID, address,
	).Scan(&txCount)
	if err != nil {
		writeInternalError(w, "Database error")
		return
	}

	// Get token count
	var tokenCount int
	err = s.db.QueryRow(ctx,
		`SELECT COUNT(DISTINCT token_contract) FROM token_transfers WHERE chain_id = $1 AND (LOWER(from_address) = $2 OR LOWER(to_address) = $2)`,
		s.chainID, address,
	).Scan(&tokenCount)
	if err != nil {
		tokenCount = 0
	}

	// Get label
	var label sql.NullString
	s.db.QueryRow(ctx,
		`SELECT label FROM address_labels WHERE chain_id = $1 AND LOWER(address) = $2 AND label_type = 'public' LIMIT 1`,
		s.chainID, address,
	).Scan(&label)

	// Get tags
	rows, err := s.db.Query(ctx,
		`SELECT tag FROM address_tags WHERE chain_id = $1 AND LOWER(address) = $2`,
		s.chainID, address,
	)
	tags := []string{}
	if err == nil {
		defer rows.Close()
		for rows.Next() {
			var tag string
			if err := rows.Scan(&tag); err == nil {
				tags = append(tags, tag)
			}
		}
	}

	// Check if contract
	var isContract bool
	s.db.QueryRow(ctx,
		`SELECT EXISTS(SELECT 1 FROM contracts WHERE chain_id = $1 AND LOWER(address) = $2)`,
		s.chainID, address,
	).Scan(&isContract)

	response := map[string]interface{}{
		"address":             address,
		"chain_id":            s.chainID,
		"balance":             nil,
		"balance_unavailable": true,
		"transaction_count":   txCount,
		"token_count":         tokenCount,
		"is_contract":         isContract,
		"tags":                tags,
	}

	if label.Valid {
		response["label"] = label.String
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"data": response,
	})
}
