package lib

import "database/sql"

// Entry is the single core data type. One table to rule them all.
type Entry struct {
	EntryID    string `json:"entry_id"`
	ProjectID  string `json:"project_id"`
	ParentID   string `json:"parent_id"`
	Type       string `json:"type"`
	Depth      int    `json:"depth"`
	SortOrder  int    `json:"sort_order"`
	SearchKey  []byte `json:"-"` // blind index (HMAC-SHA256)
	SearchKey2 []byte `json:"-"` // blind index (HMAC-SHA256)
	Summary    []byte `json:"-"` // packed: zstd + AES-256-GCM
	Data       []byte `json:"-"` // packed: zstd + AES-256-GCM
	Stage      string `json:"stage"`

	// Workflow routing (plain, indexed)
	AssigneeID string `json:"assignee_id"`
	ReturnToID string `json:"return_to_id"`
	OriginID   string `json:"origin_id"`

	// Optimistic locking
	Version int `json:"version"`

	// Soft delete
	DeletedAt *int64  `json:"deleted_at,omitempty"`
	DeletedBy *string `json:"deleted_by,omitempty"`

	// Key rotation
	KeyVersion int `json:"key_version"`

	// Timestamps
	CreatedAt int64  `json:"created_at"`
	UpdatedAt int64  `json:"updated_at"`
	CreatedBy string `json:"created_by"`

	// Unpacked fields (not stored directly, populated by lib)
	SummaryText string `json:"summary,omitempty"`
	DataText    string `json:"data_text,omitempty"`
}

// Entry types
const (
	TypeProject         = "project"
	TypeWorkstream      = "workstream"
	TypeRequestList     = "request_list"
	TypeRequest         = "request"
	TypeAnswer          = "answer"
	TypeSection         = "section"
	TypeComment         = "comment"
	TypeOrganization    = "organization"
	TypeDealOrg         = "deal_org"
	TypeRequestTemplate = "request_template" // global template stored under TemplateProjectID
)

// Stages
const (
	StagePreDataroom = "pre_dataroom"
	StageDataroom    = "dataroom"
	StageClosed      = "closed"
)

// OrgData is the JSON structure packed into an organization entry's Data field.
type OrgData struct {
	Name         string   `json:"name"`
	Domains      []string `json:"domains"`                 // required, e.g. ["kaseya.com","datto.com"]
	Role         string   `json:"role"`                    // seller | buyer | ib | advisor
	Logo         string   `json:"logo,omitempty"`
	Website      string   `json:"website,omitempty"`
	Description  string   `json:"description,omitempty"`
	Industry     string   `json:"industry,omitempty"`
	Phone        string   `json:"phone,omitempty"`
	Fax          string   `json:"fax,omitempty"`
	Address      string   `json:"address,omitempty"`
	City         string   `json:"city,omitempty"`
	State        string   `json:"state,omitempty"`
	Country      string   `json:"country,omitempty"`
	Founded      string   `json:"founded,omitempty"`
	LinkedIn     string   `json:"linkedin,omitempty"`
	ContactName  string   `json:"contact_name,omitempty"`
	ContactEmail string   `json:"contact_email,omitempty"`
}

// DealOrgData is the JSON structure packed into a deal_org entry's Data field.
// A deal_org entry links an organization into a specific deal (project).
type DealOrgData struct {
	OrgID      string          `json:"org_id"`      // entry_id of the organization
	Role       string          `json:"role"`        // seller | buyer | ib | advisor
	DomainLock bool            `json:"domain_lock"` // if true, enforce domain check on invites
	Permissions *DealOrgPerms  `json:"permissions,omitempty"`
	Members     []DealOrgMember `json:"members,omitempty"`
}

// DealOrgPerms defines what an org can do in a deal.
type DealOrgPerms struct {
	Download        string `json:"download"`          // "full" | "watermark" | "none"
	Upload          bool   `json:"upload"`
	AddRequestLists bool   `json:"add_request_lists"`
	EditRequestLists bool  `json:"edit_request_lists"`
	FolderAccess    string `json:"folder_access"`     // "all" | "assigned"
}

// DealOrgMember is a person associated with a deal org.
type DealOrgMember struct {
	Name     string `json:"name"`
	Email    string `json:"email"`
	Title    string `json:"title,omitempty"`
	Phone    string `json:"phone,omitempty"`
	Photo    string `json:"photo,omitempty"`
	Bio      string `json:"bio,omitempty"`
	LinkedIn string `json:"linkedin,omitempty"`
}

// User represents an account.
type User struct {
	UserID    string `json:"user_id"`
	Email     string `json:"email"`
	Name      string `json:"name"`
	Password  string `json:"-"` // bcrypt
	OrgID     string `json:"org_id"`
	OrgName   string `json:"org_name"`
	MFASecret string `json:"-"`
	Active    bool   `json:"active"`
	CreatedAt int64  `json:"created_at"`
	UpdatedAt int64  `json:"updated_at"`
}

// Access is an RBAC grant.
type Access struct {
	ID           string `json:"id"`
	ProjectID    string `json:"project_id"`
	WorkstreamID string `json:"workstream_id,omitempty"`
	UserID       string `json:"user_id"`
	Role         string `json:"role"`
	Ops          string `json:"ops"`
	CanGrant     bool   `json:"can_grant"`
	GrantedBy    string `json:"granted_by"`
	GrantedAt    int64  `json:"granted_at"`
	RevokedAt    *int64 `json:"revoked_at,omitempty"`
	RevokedBy    string `json:"revoked_by,omitempty"`
}

// Roles
const (
	RoleSuperAdmin   = "super_admin"
	RoleIBAdmin      = "ib_admin"
	RoleIBMember     = "ib_member"
	RoleSellerAdmin  = "seller_admin"
	RoleSellerMember = "seller_member"
	RoleBuyerAdmin   = "buyer_admin"
	RoleBuyerMember  = "buyer_member"
	RoleObserver     = "observer"
)

// RoleHierarchy defines privilege levels. Higher = more privileged.
var RoleHierarchy = map[string]int{
	RoleSuperAdmin:   200,
	RoleIBAdmin:      100,
	RoleIBMember:     80,
	RoleSellerAdmin:  70,
	RoleSellerMember: 50,
	RoleBuyerAdmin:   40,
	RoleBuyerMember:  30,
	RoleObserver:     10,
}

// AnswerLink connects answers to requests (many-to-many).
type AnswerLink struct {
	AnswerID     string   `json:"answer_id"`
	RequestID    string   `json:"request_id"`
	LinkedBy     string   `json:"linked_by"`
	LinkedAt     int64    `json:"linked_at"`
	Confirmed    bool     `json:"confirmed"`
	AIScore      *float64 `json:"ai_score,omitempty"`
	Status       string   `json:"status"`
	ReviewedBy   string   `json:"reviewed_by,omitempty"`
	ReviewedAt   *int64   `json:"reviewed_at,omitempty"`
	RejectReason string   `json:"reject_reason,omitempty"`
}

// EntryEvent is a workflow thread item.
type EntryEvent struct {
	ID      string `json:"id"`
	EntryID string `json:"entry_id"`
	ActorID string `json:"actor_id"`
	Channel string `json:"channel"`
	Action  []byte `json:"-"` // packed
	Data    []byte `json:"-"` // packed
	Ts      int64  `json:"ts"`

	ActionText string `json:"action,omitempty"`
	DataText   string `json:"data_text,omitempty"`
}

// AuditEntry is a security audit log row.
type AuditEntry struct {
	ID        string `json:"id"`
	ProjectID string `json:"project_id"`
	ActorID   string `json:"actor_id"`
	Action    []byte `json:"-"`
	TargetID  string `json:"target_id,omitempty"`
	Details   []byte `json:"-"`
	IP        string `json:"ip,omitempty"`
	Ts        int64  `json:"ts"`

	ActionText  string `json:"action,omitempty"`
	DetailsText string `json:"details,omitempty"`
}

// Session tracks active user sessions.
type Session struct {
	ID          string `json:"id"`
	UserID      string `json:"user_id"`
	Fingerprint string `json:"fingerprint"`
	CreatedAt   int64  `json:"created_at"`
	ExpiresAt   int64  `json:"expires_at"`
	Revoked     bool   `json:"revoked"`
	TestRole    string `json:"test_role,omitempty"` // super-admin test impersonation
}

// Theme is a CSS custom properties bundle.
type Theme struct {
	ID         string `json:"id"`
	Name       string `json:"name"`
	ProjectID  string `json:"project_id,omitempty"`
	Properties string `json:"properties"` // packed CSS vars as JSON
}

// EntryFilter is used by EntryRead to query entries.
type EntryFilter struct {
	ProjectID  string
	ParentID   *string
	Type       string
	Stage      string
	AssigneeID string
	SearchKey  []byte // blind index to match
	Limit      int
	Offset     int
}

// DB wraps the database connection.
type DB struct {
	Conn *sql.DB
}

// Challenge represents an email OTP challenge for passwordless login.
type Challenge struct {
	ChallengeID string `json:"challenge_id"`
	Email       string `json:"email"`
	Code        string `json:"code"`
	CreatedAt   int64  `json:"created_at"`
	ExpiresAt   int64  `json:"expires_at"`
	Used        bool   `json:"used"`
}

// Config holds application configuration.
type Config struct {
	MasterKey      []byte
	DBPath         string
	StorePath      string
	Port           string
	Env            string // "development" | "production"
	JWTSecret      []byte
	Mailer         *Mailer
	BackdoorCode   string // OTP backdoor for dev/testing
	OpenRouterKey  string // OpenRouter API key for LLM features
}

// RequestData is the JSON structure packed into a request entry's Data field.
// Represents a diligence request item imported from CSV/XLSX.
type RequestData struct {
	Title          string   `json:"title"`                      // human-readable description
	ItemNumber     string   `json:"item_number"`                // e.g. "1.3", "A-12"
	Section        string   `json:"section"`                    // e.g. "Financial", "Legal"
	Description    string   `json:"description"`                // full detail / context
	Priority       string   `json:"priority"`                   // critical | high | medium | low
	Status         string   `json:"status"`                     // open | in_process | partial | complete
	AssigneeID     string   `json:"assignee_id,omitempty"`
	AssigneeName   string   `json:"assignee_name,omitempty"`
	ReviewerID     string   `json:"reviewer_id,omitempty"`
	DueDate        string   `json:"due_date,omitempty"`         // YYYY-MM-DD
	CompletedAt    string   `json:"completed_at,omitempty"`     // YYYY-MM-DD
	BuyerComment   string   `json:"buyer_comment,omitempty"`
	SellerComment  string   `json:"seller_comment,omitempty"`
	Label          string   `json:"label,omitempty"`
	Tags           []string `json:"tags,omitempty"`
	LinkedEntryIDs []string `json:"linked_entry_ids,omitempty"` // linked answer/file entries
}

// SectionData is the JSON structure packed into a section entry's Data field.
type SectionData struct {
	Name string `json:"name"`
}

// RequestListData is the JSON structure packed into a request_list entry's Data field.
type RequestListData struct {
	Name            string `json:"name"`
	OrgID           string `json:"org_id,omitempty"`            // PE firm org entry_id
	VisibilityOrgID string `json:"visibility_org_id,omitempty"` // restrict visibility to this org (+ IB)
}

// RequestTemplateData is the JSON structure packed into a request_template entry's Data field.
type RequestTemplateData struct {
	Name        string              `json:"name"`
	Description string              `json:"description,omitempty"`
	Items       []RequestTemplateItem `json:"items"`
}

// RequestTemplateItem is a single item in a request template.
type RequestTemplateItem struct {
	Section    string `json:"section"`
	ItemNumber string `json:"item_number,omitempty"`
	Title      string `json:"title"`
	Priority   string `json:"priority,omitempty"`
}

// WorkstreamData is the JSON structure packed into a workstream entry's Data field.
type WorkstreamData struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
}

// OAuthClient represents a registered OAuth 2.0 client application.
type OAuthClient struct {
	ClientID     string   `json:"client_id"`
	ClientName   string   `json:"client_name"`
	RedirectURIs []string `json:"redirect_uris"`
	CreatedAt    int64    `json:"created_at"`
}

// OAuthCode represents an OAuth 2.0 authorization code.
type OAuthCode struct {
	Code          string `json:"code"`
	ClientID      string `json:"client_id"`
	UserID        string `json:"user_id"`
	RedirectURI   string `json:"redirect_uri"`
	CodeChallenge string `json:"code_challenge"`
	Scope         string `json:"scope"`
	ExpiresAt     int64  `json:"expires_at"`
	Used          bool   `json:"used"`
}

// OAuthToken represents an OAuth 2.0 access token.
type OAuthToken struct {
	Token     string `json:"token"`
	ClientID  string `json:"client_id"`
	UserID    string `json:"user_id"`
	Scope     string `json:"scope"`
	ExpiresAt int64  `json:"expires_at"`
	Revoked   bool   `json:"revoked"`
	CreatedAt int64  `json:"created_at"`
}
