package services

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

// ShieldClient cliente HTTP para la API de USITE Shield.
type ShieldClient struct {
	baseURL    string
	adminToken string
	http       *http.Client
}

func NewShieldClient(baseURL, adminToken string) *ShieldClient {
	if baseURL == "" {
		baseURL = "https://api-shield.u-s.app"
	}
	return &ShieldClient{
		baseURL:    baseURL,
		adminToken: adminToken,
		http:       &http.Client{Timeout: 15 * time.Second},
	}
}

func (s *ShieldClient) do(method, path string, body interface{}) ([]byte, int, error) {
	var bodyReader io.Reader
	if body != nil {
		b, err := json.Marshal(body)
		if err != nil {
			return nil, 0, err
		}
		bodyReader = bytes.NewReader(b)
	}
	req, err := http.NewRequest(method, s.baseURL+path, bodyReader)
	if err != nil {
		return nil, 0, err
	}
	req.Header.Set("Content-Type", "application/json")
	if s.adminToken != "" {
		req.Header.Set("Authorization", "Bearer "+s.adminToken)
	}
	resp, err := s.http.Do(req)
	if err != nil {
		return nil, 0, err
	}
	defer resp.Body.Close()
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, resp.StatusCode, err
	}
	if resp.StatusCode >= 400 {
		// La API puede devolver texto plano en errores; evitamos que el caller intente parsear JSON
		msg := string(data)
		if msg == "" {
			msg = resp.Status
		}
		return nil, resp.StatusCode, fmt.Errorf("shield API error %d: %s", resp.StatusCode, msg)
	}
	return data, resp.StatusCode, nil
}

// ─── Health ──────────────────────────────────────────────────────────────────

func (s *ShieldClient) Health() (map[string]interface{}, error) {
	data, _, err := s.do("GET", "/health", nil)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	return out, json.Unmarshal(data, &out)
}

// ─── Extension version ───────────────────────────────────────────────────────

func (s *ShieldClient) ExtensionVersion() (map[string]interface{}, error) {
	data, _, err := s.do("GET", "/api/extension/version", nil)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	return out, json.Unmarshal(data, &out)
}

// ─── Logs ────────────────────────────────────────────────────────────────────

func (s *ShieldClient) Logs(limit int, path, method string) (map[string]interface{}, error) {
	q := fmt.Sprintf("/api/admin/logs?limit=%d", limit)
	if path != "" {
		q += "&path=" + path
	}
	if method != "" {
		q += "&method=" + method
	}
	data, _, err := s.do("GET", q, nil)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	return out, json.Unmarshal(data, &out)
}

func (s *ShieldClient) LogStats() (map[string]interface{}, error) {
	data, _, err := s.do("GET", "/api/admin/logs/stats", nil)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	return out, json.Unmarshal(data, &out)
}

// ─── Review requests ─────────────────────────────────────────────────────────

func (s *ShieldClient) ReviewRequests(status string) (map[string]interface{}, error) {
	if status == "" {
		status = "pending"
	}
	data, _, err := s.do("GET", "/api/admin/review-requests?status="+status, nil)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	return out, json.Unmarshal(data, &out)
}

func (s *ShieldClient) ApproveRequest(id, note, reason string) (map[string]interface{}, error) {
	body := map[string]string{"note": note, "reason": reason}
	data, _, err := s.do("PUT", "/api/admin/review-requests/"+id+"/approve", body)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	json.Unmarshal(data, &out)
	return out, nil
}

func (s *ShieldClient) RejectRequest(id, note string) (map[string]interface{}, error) {
	body := map[string]string{"note": note}
	data, _, err := s.do("PUT", "/api/admin/review-requests/"+id+"/reject", body)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	json.Unmarshal(data, &out)
	return out, nil
}

// ─── Whitelist ───────────────────────────────────────────────────────────────

func (s *ShieldClient) Whitelist() (map[string]interface{}, error) {
	data, _, err := s.do("GET", "/api/admin/whitelist", nil)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	return out, json.Unmarshal(data, &out)
}

func (s *ShieldClient) AddWhitelist(domain, reason, addedBy string) (map[string]interface{}, error) {
	body := map[string]string{"domain": domain, "reason": reason, "added_by": addedBy}
	data, _, err := s.do("POST", "/api/admin/whitelist", body)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	json.Unmarshal(data, &out)
	return out, nil
}

func (s *ShieldClient) DeleteWhitelist(domain string) error {
	_, _, err := s.do("DELETE", "/api/admin/whitelist/"+domain, nil)
	return err
}

// ─── Blacklist ───────────────────────────────────────────────────────────────

func (s *ShieldClient) Blacklist() (map[string]interface{}, error) {
	data, _, err := s.do("GET", "/api/admin/blacklist", nil)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	return out, json.Unmarshal(data, &out)
}

func (s *ShieldClient) AddBlacklist(domain, reason, addedBy string) (map[string]interface{}, error) {
	body := map[string]string{"domain": domain, "reason": reason, "added_by": addedBy}
	data, _, err := s.do("POST", "/api/admin/blacklist", body)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	json.Unmarshal(data, &out)
	return out, nil
}

func (s *ShieldClient) DeleteBlacklist(domain string) error {
	_, _, err := s.do("DELETE", "/api/admin/blacklist/"+domain, nil)
	return err
}

// ─── Reputación ──────────────────────────────────────────────────────────────

func (s *ShieldClient) Reputation(domain string) (map[string]interface{}, error) {
	data, _, err := s.do("GET", "/api/reputation/"+domain, nil)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	return out, json.Unmarshal(data, &out)
}

func (s *ShieldClient) AdjustScore(domain string, votesReal, votesFake int) (map[string]interface{}, error) {
	body := map[string]int{"votes_real": votesReal, "votes_fake": votesFake}
	data, _, err := s.do("PUT", "/api/admin/reputation/"+domain+"/score", body)
	if err != nil {
		return nil, err
	}
	var out map[string]interface{}
	json.Unmarshal(data, &out)
	return out, nil
}
