package main

import (
	"fmt"
	"log"
	"time"

	"github.com/google/uuid"
	"github.com/mish/dealspace/lib"
)

// seedSuperAdmins ensures the super admin accounts always exist.
// Called on every startup (not just when SEED_DEMO=true).
func seedSuperAdmins(db *lib.DB) {
	type admin struct {
		email   string
		name    string
		orgID   string
		orgName string
	}
	admins := []admin{
		{"michael@muskepo.com", "Michael", "muskepo", "Muskepo"},
		{"johan@jongsma.me", "Johan", "muskepo", "Muskepo"},
	}

	for _, a := range admins {
		existing, err := lib.UserByEmail(db, a.email)
		if err != nil {
			log.Printf("seed: check %s: %v", a.email, err)
			continue
		}
		if existing != nil {
			// User exists, ensure they have super_admin access
			ensureSuperAdmin(db, existing.UserID)
			continue
		}

		now := time.Now().UnixMilli()
		userID := uuid.New().String()
		user := &lib.User{
			UserID:    userID,
			Email:     a.email,
			Name:      a.name,
			Password:  "", // passwordless auth — no password needed
			OrgID:     a.orgID,
			OrgName:   a.orgName,
			Active:    true,
			CreatedAt: now,
			UpdatedAt: now,
		}
		if err := lib.UserCreate(db, user); err != nil {
			log.Printf("seed: create %s: %v", a.email, err)
			continue
		}
		log.Printf("seed: created super admin %s", a.email)
		ensureSuperAdmin(db, userID)
	}
}

// ensureSuperAdmin grants super_admin role on the special "*" project (platform-wide).
func ensureSuperAdmin(db *lib.DB, userID string) {
	// Check if already has super_admin
	isSuperAdmin, _ := lib.IsSuperAdmin(db, userID)
	if isSuperAdmin {
		return
	}

	now := time.Now().UnixMilli()
	access := &lib.Access{
		ID:        uuid.New().String(),
		ProjectID: "*", // platform-wide
		UserID:    userID,
		Role:      lib.RoleSuperAdmin,
		Ops:       "rwdm",
		CanGrant:  true,
		GrantedBy: "system",
		GrantedAt: now,
	}
	if err := lib.AccessGrant(db, access); err != nil {
		log.Printf("seed: grant super_admin to %s: %v", userID, err)
		return
	}
	log.Printf("seed: granted super_admin to %s", userID)
}

func seedDemoData(db *lib.DB, cfg *lib.Config) {
	count, err := lib.UserCount(db)
	if err != nil {
		log.Printf("seed: cannot check user count: %v", err)
		return
	}
	// Only seed demo data if no users exist (besides super admins)
	if count > 2 {
		log.Printf("seed: users already exist, skipping demo data")
		return
	}

	log.Printf("seed: creating demo data...")
	now := time.Now().UnixMilli()

	// Create demo user: admin@demo.com (passwordless — no password needed)
	adminID := uuid.New().String()
	admin := &lib.User{
		UserID:    adminID,
		Email:     "admin@demo.com",
		Name:      "Demo Admin",
		Password:  "",
		OrgID:     "demo-org",
		OrgName:   "Demo Investment Bank",
		Active:    true,
		CreatedAt: now,
		UpdatedAt: now,
	}
	if err := lib.UserCreate(db, admin); err != nil {
		log.Printf("seed: create admin: %v", err)
		return
	}
	log.Printf("seed: created admin user admin@demo.com")

	// Create demo project: TechCorp Acquisition
	projectID := uuid.New().String()
	projectData := `{"name":"TechCorp Acquisition","deal_type":"sell_side","status":"active"}`

	key, err := lib.DeriveProjectKey(cfg.MasterKey, projectID)
	if err != nil {
		log.Printf("seed: derive key: %v", err)
		return
	}

	summaryPacked, _ := lib.Pack(key, "TechCorp Acquisition")
	dataPacked, _ := lib.Pack(key, projectData)

	_, err = db.Conn.Exec(
		`INSERT INTO entries (entry_id, project_id, parent_id, type, depth,
		  search_key, search_key2, summary, data, stage,
		  assignee_id, return_to_id, origin_id,
		  version, key_version, created_at, updated_at, created_by)
		 VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?, ?,?,?,?,?)`,
		projectID, projectID, "", lib.TypeProject, 0,
		nil, nil, summaryPacked, dataPacked, lib.StagePreDataroom,
		"", "", "",
		1, 1, now, now, adminID,
	)
	if err != nil {
		log.Printf("seed: create project: %v", err)
		return
	}

	// Grant ib_admin access
	accessID := uuid.New().String()
	_, err = db.Conn.Exec(
		`INSERT INTO access (id, project_id, workstream_id, user_id, role, ops, can_grant, granted_by, granted_at)
		 VALUES (?,?,?,?,?,?,?,?,?)`,
		accessID, projectID, nil, adminID, lib.RoleIBAdmin, "rwdm", 1, adminID, now,
	)
	if err != nil {
		log.Printf("seed: grant access: %v", err)
		return
	}

	// Also grant super admins access to the demo project
	grantSuperAdminsToProject(db, projectID, now)

	// Create workstreams: Finance, Legal, IT
	workstreams := []string{"Finance", "Legal", "IT"}
	wsIDs := make([]string, len(workstreams))
	for i, name := range workstreams {
		wsID := uuid.New().String()
		wsIDs[i] = wsID
		wsSummary, _ := lib.Pack(key, name)
		wsData, _ := lib.Pack(key, fmt.Sprintf(`{"name":"%s"}`, name))

		_, err = db.Conn.Exec(
			`INSERT INTO entries (entry_id, project_id, parent_id, type, depth,
			  search_key, search_key2, summary, data, stage,
			  assignee_id, return_to_id, origin_id,
			  version, key_version, created_at, updated_at, created_by)
			 VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?, ?,?,?,?,?)`,
			wsID, projectID, projectID, lib.TypeWorkstream, 1,
			nil, nil, wsSummary, wsData, lib.StagePreDataroom,
			"", "", "",
			1, 1, now, now, adminID,
		)
		if err != nil {
			log.Printf("seed: create workstream %s: %v", name, err)
		}
	}
	log.Printf("seed: created 3 workstreams")

	// Create 5 sample requests in Finance workstream
	type seedReq struct {
		ref, title, body, priority, due string
	}
	requests := []seedReq{
		{"FIN-001", "Audited financial statements FY2023-2025", "Provide complete audited financial statements for fiscal years 2023, 2024, and 2025.", "high", "2026-03-15"},
		{"FIN-002", "Revenue breakdown by customer (top 20)", "Break down revenue by top 20 customers showing percentage of total revenue.", "high", "2026-03-15"},
		{"FIN-003", "Cap table and option pool details", "Provide current capitalization table including all share classes and warrants.", "normal", "2026-03-20"},
		{"FIN-004", "AR/AP aging reports", "Accounts receivable and accounts payable aging reports as of most recent month-end.", "normal", "2026-03-25"},
		{"FIN-005", "Revenue recognition policy", "Document your revenue recognition policy including any changes in past 3 fiscal years.", "low", "2026-03-30"},
	}

	for _, req := range requests {
		reqID := uuid.New().String()
		reqData := fmt.Sprintf(`{"title":"%s","body":"%s","priority":"%s","due_date":"%s","status":"open","ref":"%s"}`,
			req.title, req.body, req.priority, req.due, req.ref)

		reqSummary, _ := lib.Pack(key, req.title)
		reqDataPacked, _ := lib.Pack(key, reqData)

		_, err = db.Conn.Exec(
			`INSERT INTO entries (entry_id, project_id, parent_id, type, depth,
			  search_key, search_key2, summary, data, stage,
			  assignee_id, return_to_id, origin_id,
			  version, key_version, created_at, updated_at, created_by)
			 VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?, ?,?,?,?,?)`,
			reqID, projectID, wsIDs[0], lib.TypeRequest, 3,
			nil, nil, reqSummary, reqDataPacked, lib.StagePreDataroom,
			adminID, "", "",
			1, 1, now, now, adminID,
		)
		if err != nil {
			log.Printf("seed: create request %s: %v", req.ref, err)
		}
	}
	log.Printf("seed: created 5 sample requests in Finance workstream")
	log.Printf("seed: done! Login with admin@demo.com, michael@muskepo.com, or johan@jongsma.me")
}

// grantSuperAdminsToProject gives super admin users ib_admin access on a project.
func grantSuperAdminsToProject(db *lib.DB, projectID string, now int64) {
	emails := []string{"michael@muskepo.com", "johan@jongsma.me"}
	for _, email := range emails {
		user, err := lib.UserByEmail(db, email)
		if err != nil || user == nil {
			continue
		}
		accessID := uuid.New().String()
		_, _ = db.Conn.Exec(
			`INSERT OR IGNORE INTO access (id, project_id, workstream_id, user_id, role, ops, can_grant, granted_by, granted_at)
			 VALUES (?,?,?,?,?,?,?,?,?)`,
			accessID, projectID, nil, user.UserID, lib.RoleIBAdmin, "rwdm", 1, "system", now,
		)
	}
}
