package scanner

import (
	"encoding/json"
	"fmt"
	"os"
	"time"

	"github.com/dd0c/drift-agent/pkg/models"
)

// Scanner reads Terraform state and computes drift diffs.
type Scanner struct {
	scrubber *Scrubber
}

func New(scrubber *Scrubber) *Scanner {
	return &Scanner{scrubber: scrubber}
}

// TerraformState represents the v4 state file format.
type TerraformState struct {
	Version          int              `json:"version"`
	TerraformVersion string           `json:"terraform_version"`
	Serial           int64            `json:"serial"`
	Lineage          string           `json:"lineage"`
	Resources        []StateResource  `json:"resources"`
}

type StateResource struct {
	Module    string           `json:"module,omitempty"`
	Mode      string           `json:"mode"`     // "managed" or "data"
	Type      string           `json:"type"`
	Name      string           `json:"name"`
	Provider  string           `json:"provider"`
	Instances []StateInstance  `json:"instances"`
}

type StateInstance struct {
	SchemaVersion int                    `json:"schema_version"`
	Attributes    map[string]interface{} `json:"attributes"`
	Private       string                 `json:"private,omitempty"`
}

// ScanResult is the output of a drift scan.
type ScanResult struct {
	StackName    string              `json:"stack_name"`
	ScannedAt    time.Time           `json:"scanned_at"`
	StateSerial  int64               `json:"state_serial"`
	Lineage      string              `json:"lineage"`
	TotalResources int               `json:"total_resources"`
	DriftedResources []models.DriftedResource `json:"drifted_resources"`
}

// ScanFromFile reads a local tfstate file and produces a ScanResult.
func (s *Scanner) ScanFromFile(path string, stackName string) (*ScanResult, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read state file: %w", err)
	}

	var state TerraformState
	if err := json.Unmarshal(data, &state); err != nil {
		return nil, fmt.Errorf("parse state file: %w", err)
	}

	if state.Version != 4 {
		return nil, fmt.Errorf("unsupported state version %d (expected 4)", state.Version)
	}

	result := &ScanResult{
		StackName:    stackName,
		ScannedAt:    time.Now().UTC(),
		StateSerial:  state.Serial,
		Lineage:      state.Lineage,
		TotalResources: countResources(&state),
		DriftedResources: []models.DriftedResource{},
	}

	// TODO: Compare state attributes against live cloud resources
	// For V1, we compare against the previous state snapshot stored in SaaS

	// Scrub sensitive values from the result
	if s.scrubber != nil {
		for i := range result.DriftedResources {
			result.DriftedResources[i] = s.scrubber.ScrubResource(result.DriftedResources[i])
		}
	}

	return result, nil
}

func countResources(state *TerraformState) int {
	count := 0
	for _, r := range state.Resources {
		if r.Mode == "managed" {
			count += len(r.Instances)
		}
	}
	return count
}
