package user

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"log"
	"log/slog"
	"net/http"
	"os"

	"crussell/db"
	"crussell/handlers/payments"
	"crussell/internal/dav"
	"crussell/internal/s3"
	"crussell/mw"
	"github.com/jackc/pgx/v5"
)

// DELETE /api/user/account
func DeleteAccountHandler(w http.ResponseWriter, r *http.Request) {
	userID, ok := mw.GetUserID(r.Context())
	if !ok {
		http.Error(w, "unauthorized", http.StatusUnauthorized)
		return
	}

	var accountRole string
	var profilePicURL sql.NullString
	err := db.Conn.QueryRow(r.Context(), `SELECT account_role, profile_pic_url FROM users WHERE id = $1`, userID).
		Scan(&accountRole, &profilePicURL)
	if err != nil {
		if errors.Is(err, pgx.ErrNoRows) {
			http.Error(w, "user not found", http.StatusNotFound)
			return
		}
		log.Printf("Failed to fetch user for deletion: %v", err)
		http.Error(w, "server error", http.StatusInternalServerError)
		return
	}

	ctx := r.Context()

	// --- External system scrubbing (BEFORE SQL anonymize) ---

	// Delete profile picture from S3/R2
	if profilePicURL.Valid && profilePicURL.String != "" && s3.Client != nil {
		go func(picURL string) {
			defer func() {
				if r := recover(); r != nil {
					log.Printf("Panic recovered in S3 profile picture deletion: %v", r)
				}
			}()
			bucket := os.Getenv("S3_PROFILE_PICS_BUCKET")
			if bucket == "" {
				bucket = "crussell-profile-pics"
			}
			// profiles/{userID}.jpg — matches UploadProfilePictureHandler key format
			key := fmt.Sprintf("profiles/%s.jpg", userID)
			if err := s3.Client.Delete(context.Background(), bucket, key); err != nil {
				log.Printf("Warning: Failed to delete profile picture for user %s: %v", userID, err)
			}
		}(profilePicURL.String)
	}

	if payments.SquareClient != nil {
		go func() {
			defer func() {
				if r := recover(); r != nil {
					log.Printf("Panic recovered in Square saved card cleanup: %v", r)
				}
			}()
			rows, err := db.Conn.Query(context.Background(),
				`SELECT square_card_id FROM user_saved_cards WHERE user_id = $1 AND deleted_at IS NULL`, userID)
			if err != nil {
				log.Printf("Warning: Failed to query saved cards for user %s: %v", userID, err)
				return
			}
			defer rows.Close()
			for rows.Next() {
				var cardID string
				if err := rows.Scan(&cardID); err != nil {
					log.Printf("Warning: Failed to scan card ID for user %s: %v", userID, err)
					continue
				}
				if err := payments.SquareClient.DeleteCardOnFile(context.Background(), cardID); err != nil {
					log.Printf("Warning: Failed to delete Square card %s for user %s: %v", cardID, userID, err)
				}
			}
			if err := rows.Err(); err != nil {
				log.Printf("Warning: Row iteration error for user %s: %v", userID, err)
				return
			}
		}()
	}

	// --- SQL-level anonymization/deletion ---

	if accountRole == "guest" {
		tx, err := db.Conn.Begin(ctx)
		if err != nil {
			log.Printf("Failed to begin transaction for guest user deletion: %v", err)
			http.Error(w, "server error", http.StatusInternalServerError)
			return
		}
		defer func() {
    if err := tx.Rollback(ctx); err != nil {
        slog.Error("failed to rollback transaction", "err", err)
    }
}()

		_, err = tx.Exec(ctx, `SELECT delete_guest_user($1)`, userID)
		if err != nil {
			log.Printf("Failed to delete guest user %s: %v", userID, err)
			http.Error(w, "server error", http.StatusInternalServerError)
			return
		}

		if err := tx.Commit(ctx); err != nil {
			log.Printf("Failed to commit transaction for guest user deletion: %v", err)
			http.Error(w, "server error", http.StatusInternalServerError)
			return
		}
	} else {
		tx, err := db.Conn.Begin(ctx)
		if err != nil {
			log.Printf("Failed to begin transaction for user anonymization: %v", err)
			http.Error(w, "server error", http.StatusInternalServerError)
			return
		}
		defer func() {
    if err := tx.Rollback(ctx); err != nil {
        slog.Error("failed to rollback transaction", "err", err)
    }
}()

		_, err = tx.Exec(ctx, `SELECT anonymize_user($1)`, userID)
		if err != nil {
			log.Printf("Failed to anonymize user %s: %v", userID, err)
			http.Error(w, "server error", http.StatusInternalServerError)
			return
		}

		if err := tx.Commit(ctx); err != nil {
			log.Printf("Failed to commit transaction for user anonymization: %v", err)
			http.Error(w, "server error", http.StatusInternalServerError)
			return
		}

		// TODO: Create 'user_anonymized' notification for admin audit trail
	}

	// Delete CardDAV contact (non-blocking, best-effort)
	if dav.Service != nil {
		go func() {
			defer func() {
				if r := recover(); r != nil {
					log.Printf("Panic recovered in CardDAV contact deletion: %v", r)
				}
			}()
			uri := fmt.Sprintf("%s.vcf", userID)
			if err := dav.Service.DeleteContact(1, uri); err != nil {
				log.Printf("Warning: Failed to delete CardDAV contact for user %s: %v", userID, err)
			}
		}()
	}

	w.WriteHeader(http.StatusNoContent)
}
