package store

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

	"git.warky.dev/wdevs/amcs/internal/generatedmodels"
	ext "git.warky.dev/wdevs/amcs/internal/types"
)

func projectFromModel(m generatedmodels.ModelPublicProjects) ext.Project {
	return ext.Project{
		ID:           m.GUID.UUID(),
		NumericID:    m.ID.Int64(),
		Name:         m.Name.String(),
		Description:  m.Description.String(),
		CreatedAt:    m.CreatedAt.Time(),
		LastActiveAt: m.LastActiveAt.Time(),
	}
}

func thoughtFromModel(m generatedmodels.ModelPublicThoughts) (ext.Thought, error) {
	var metadata ext.ThoughtMetadata
	if len(m.Metadata) > 0 {
		if err := json.Unmarshal(m.Metadata, &metadata); err != nil {
			return ext.Thought{}, fmt.Errorf("decode thought metadata: %w", err)
		}
	}

	var projectID *int64
	if m.ProjectID.Valid {
		id := m.ProjectID.Int64()
		projectID = &id
	}

	var archivedAt *time.Time
	if m.ArchivedAt.Valid {
		t := m.ArchivedAt.Time()
		archivedAt = &t
	}

	return ext.Thought{
		ID:         m.ID.Int64(),
		GUID:       m.GUID.UUID(),
		Content:    m.Content.String(),
		Metadata:   metadata,
		ProjectID:  projectID,
		ArchivedAt: archivedAt,
		CreatedAt:  m.CreatedAt.Time(),
		UpdatedAt:  m.UpdatedAt.Time(),
	}, nil
}

func storedFileFromModel(m generatedmodels.ModelPublicStoredFiles) ext.StoredFile {
	var thoughtID *int64
	if m.ThoughtID.Valid {
		id := m.ThoughtID.Int64()
		thoughtID = &id
	}

	var projectID *int64
	if m.ProjectID.Valid {
		id := m.ProjectID.Int64()
		projectID = &id
	}

	return ext.StoredFile{
		ID:        m.ID.Int64(),
		GUID:      m.GUID.UUID(),
		ThoughtID: thoughtID,
		ProjectID: projectID,
		Name:      m.Name.String(),
		MediaType: m.MediaType.String(),
		Kind:      m.Kind.String(),
		Encoding:  m.Encoding.String(),
		SizeBytes: m.SizeBytes,
		SHA256:    m.Sha256.String(),
		Content:   m.Content,
		CreatedAt: m.CreatedAt.Time(),
		UpdatedAt: m.UpdatedAt.Time(),
	}
}

// func maintenanceTaskFromModel(m generatedmodels.ModelPublicMaintenanceTasks) ext.MaintenanceTask {
// 	var frequencyDays *int
// 	if m.FrequencyDays.Valid {
// 		n := int(m.FrequencyDays.Int64())
// 		frequencyDays = &n
// 	}

// 	var lastCompleted *time.Time
// 	if m.LastCompleted.Valid {
// 		t := m.LastCompleted.Time()
// 		lastCompleted = &t
// 	}

// 	var nextDue *time.Time
// 	if m.NextDue.Valid {
// 		t := m.NextDue.Time()
// 		nextDue = &t
// 	}

// 	return ext.MaintenanceTask{
// 		ID:            m.ID.UUID(),
// 		Name:          m.Name.String(),
// 		Category:      m.Category.String(),
// 		FrequencyDays: frequencyDays,
// 		LastCompleted: lastCompleted,
// 		NextDue:       nextDue,
// 		Priority:      m.Priority.String(),
// 		Notes:         m.Notes.String(),
// 		CreatedAt:     m.CreatedAt.Time(),
// 		UpdatedAt:     m.UpdatedAt.Time(),
// 	}
// }

// func maintenanceLogFromModel(m generatedmodels.ModelPublicMaintenanceLogs) ext.MaintenanceLog {
// 	var cost *float64
// 	if m.Cost.Valid {
// 		v := m.Cost.Float64()
// 		cost = &v
// 	}

// 	return ext.MaintenanceLog{
// 		ID:          m.ID.UUID(),
// 		TaskID:      m.TaskID.UUID(),
// 		CompletedAt: m.CompletedAt.Time(),
// 		PerformedBy: m.PerformedBy.String(),
// 		Cost:        cost,
// 		Notes:       m.Notes.String(),
// 		NextAction:  m.NextAction.String(),
// 	}
// }

// func householdItemFromModel(m generatedmodels.ModelPublicHouseholdItems) ext.HouseholdItem {
// 	details := map[string]any{}
// 	if len(m.Details) > 0 {
// 		if err := json.Unmarshal(m.Details, &details); err != nil {
// 			details = map[string]any{}
// 		}
// 	}

// 	return ext.HouseholdItem{
// 		ID:        m.ID.UUID(),
// 		Name:      m.Name.String(),
// 		Category:  m.Category.String(),
// 		Location:  m.Location.String(),
// 		Details:   details,
// 		Notes:     m.Notes.String(),
// 		CreatedAt: m.CreatedAt.Time(),
// 		UpdatedAt: m.UpdatedAt.Time(),
// 	}
// }

// func householdVendorFromModel(m generatedmodels.ModelPublicHouseholdVendors) ext.HouseholdVendor {
// 	var rating *int
// 	if m.Rating.Valid {
// 		v := int(m.Rating.Int64())
// 		rating = &v
// 	}

// 	var lastUsed *time.Time
// 	if m.LastUsed.Valid {
// 		t := m.LastUsed.Time()
// 		lastUsed = &t
// 	}

// 	return ext.HouseholdVendor{
// 		ID:          m.ID.UUID(),
// 		Name:        m.Name.String(),
// 		ServiceType: m.ServiceType.String(),
// 		Phone:       m.Phone.String(),
// 		Email:       m.Email.String(),
// 		Website:     m.Website.String(),
// 		Notes:       m.Notes.String(),
// 		Rating:      rating,
// 		LastUsed:    lastUsed,
// 		CreatedAt:   m.CreatedAt.Time(),
// 	}
// }

// func familyMemberFromModel(m generatedmodels.ModelPublicFamilyMembers) ext.FamilyMember {
// 	var birthDate *time.Time
// 	if m.BirthDate.Valid {
// 		t := m.BirthDate.Time()
// 		birthDate = &t
// 	}

// 	return ext.FamilyMember{
// 		ID:           m.ID.UUID(),
// 		Name:         m.Name.String(),
// 		Relationship: m.Relationship.String(),
// 		BirthDate:    birthDate,
// 		Notes:        m.Notes.String(),
// 		CreatedAt:    m.CreatedAt.Time(),
// 	}
// }

// func activityFromModel(m generatedmodels.ModelPublicActivities, memberName string) ext.Activity {
// 	var familyMemberID *uuid.UUID
// 	if m.FamilyMemberID.Valid {
// 		id := m.FamilyMemberID.UUID()
// 		familyMemberID = &id
// 	}

// 	var startDate *time.Time
// 	if m.StartDate.Valid {
// 		t := m.StartDate.Time()
// 		startDate = &t
// 	}

// 	var endDate *time.Time
// 	if m.EndDate.Valid {
// 		t := m.EndDate.Time()
// 		endDate = &t
// 	}

// 	return ext.Activity{
// 		ID:             m.ID.UUID(),
// 		FamilyMemberID: familyMemberID,
// 		MemberName:     memberName,
// 		Title:          m.Title.String(),
// 		ActivityType:   m.ActivityType.String(),
// 		DayOfWeek:      m.DayOfWeek.String(),
// 		StartTime:      m.StartTime.String(),
// 		EndTime:        m.EndTime.String(),
// 		StartDate:      startDate,
// 		EndDate:        endDate,
// 		Location:       m.Location.String(),
// 		Notes:          m.Notes.String(),
// 		CreatedAt:      m.CreatedAt.Time(),
// 	}
// }

// func importantDateFromModel(m generatedmodels.ModelPublicImportantDates, memberName string) ext.ImportantDate {
// 	var familyMemberID *uuid.UUID
// 	if m.FamilyMemberID.Valid {
// 		id := m.FamilyMemberID.UUID()
// 		familyMemberID = &id
// 	}

// 	return ext.ImportantDate{
// 		ID:                 m.ID.UUID(),
// 		FamilyMemberID:     familyMemberID,
// 		MemberName:         memberName,
// 		Title:              m.Title.String(),
// 		DateValue:          m.DateValue.Time(),
// 		RecurringYearly:    m.RecurringYearly,
// 		ReminderDaysBefore: int(m.ReminderDaysBefore),
// 		Notes:              m.Notes.String(),
// 		CreatedAt:          m.CreatedAt.Time(),
// 	}
// }

// func professionalContactFromModel(m generatedmodels.ModelPublicProfessionalContacts, tags []string) ext.ProfessionalContact {
// 	var lastContacted *time.Time
// 	if m.LastContacted.Valid {
// 		t := m.LastContacted.Time()
// 		lastContacted = &t
// 	}

// 	var followUpDate *time.Time
// 	if m.FollowUpDate.Valid {
// 		t := m.FollowUpDate.Time()
// 		followUpDate = &t
// 	}

// 	return ext.ProfessionalContact{
// 		ID:            m.ID.UUID(),
// 		Name:          m.Name.String(),
// 		Company:       m.Company.String(),
// 		Title:         m.Title.String(),
// 		Email:         m.Email.String(),
// 		Phone:         m.Phone.String(),
// 		LinkedInURL:   m.LinkedinURL.String(),
// 		HowWeMet:      m.HowWeMet.String(),
// 		Tags:          tags,
// 		Notes:         m.Notes.String(),
// 		LastContacted: lastContacted,
// 		FollowUpDate:  followUpDate,
// 		CreatedAt:     m.CreatedAt.Time(),
// 		UpdatedAt:     m.UpdatedAt.Time(),
// 	}
// }

// func contactInteractionFromModel(m generatedmodels.ModelPublicContactInteractions) ext.ContactInteraction {
// 	return ext.ContactInteraction{
// 		ID:              m.ID.UUID(),
// 		ContactID:       m.ContactID.UUID(),
// 		InteractionType: m.InteractionType.String(),
// 		OccurredAt:      m.OccurredAt.Time(),
// 		Summary:         m.Summary.String(),
// 		FollowUpNeeded:  m.FollowUpNeeded,
// 		FollowUpNotes:   m.FollowUpNotes.String(),
// 		CreatedAt:       m.CreatedAt.Time(),
// 	}
// }

// func opportunityFromModel(m generatedmodels.ModelPublicOpportunities) ext.Opportunity {
// 	var contactID *uuid.UUID
// 	if m.ContactID.Valid {
// 		id := m.ContactID.UUID()
// 		contactID = &id
// 	}

// 	var value *float64
// 	if m.Value.Valid {
// 		v := m.Value.Float64()
// 		value = &v
// 	}

// 	var expectedCloseDate *time.Time
// 	if m.ExpectedCloseDate.Valid {
// 		t := m.ExpectedCloseDate.Time()
// 		expectedCloseDate = &t
// 	}

// 	return ext.Opportunity{
// 		ID:                m.ID.UUID(),
// 		ContactID:         contactID,
// 		Title:             m.Title.String(),
// 		Description:       m.Description.String(),
// 		Stage:             m.Stage.String(),
// 		Value:             value,
// 		ExpectedCloseDate: expectedCloseDate,
// 		Notes:             m.Notes.String(),
// 		CreatedAt:         m.CreatedAt.Time(),
// 		UpdatedAt:         m.UpdatedAt.Time(),
// 	}
// }

// func recipeFromModel(m generatedmodels.ModelPublicRecipes, tags []string) ext.Recipe {
// 	var prepTimeMinutes *int
// 	if m.PrepTimeMinutes.Valid {
// 		v := int(m.PrepTimeMinutes.Int64())
// 		prepTimeMinutes = &v
// 	}

// 	var cookTimeMinutes *int
// 	if m.CookTimeMinutes.Valid {
// 		v := int(m.CookTimeMinutes.Int64())
// 		cookTimeMinutes = &v
// 	}

// 	var servings *int
// 	if m.Servings.Valid {
// 		v := int(m.Servings.Int64())
// 		servings = &v
// 	}

// 	var rating *int
// 	if m.Rating.Valid {
// 		v := int(m.Rating.Int64())
// 		rating = &v
// 	}

// 	recipe := ext.Recipe{
// 		ID:              m.ID.UUID(),
// 		Name:            m.Name.String(),
// 		Cuisine:         m.Cuisine.String(),
// 		PrepTimeMinutes: prepTimeMinutes,
// 		CookTimeMinutes: cookTimeMinutes,
// 		Servings:        servings,
// 		Tags:            tags,
// 		Rating:          rating,
// 		Notes:           m.Notes.String(),
// 		CreatedAt:       m.CreatedAt.Time(),
// 		UpdatedAt:       m.UpdatedAt.Time(),
// 	}

// 	if err := json.Unmarshal(m.Ingredients, &recipe.Ingredients); err != nil {
// 		recipe.Ingredients = []ext.Ingredient{}
// 	}
// 	if err := json.Unmarshal(m.Instructions, &recipe.Instructions); err != nil {
// 		recipe.Instructions = []string{}
// 	}
// 	return recipe
// }

// func mealPlanEntryFromModel(m generatedmodels.ModelPublicMealPlans, recipeName string) ext.MealPlanEntry {
// 	var recipeID *uuid.UUID
// 	if m.RecipeID.Valid {
// 		id := m.RecipeID.UUID()
// 		recipeID = &id
// 	}

// 	var servings *int
// 	if m.Servings.Valid {
// 		v := int(m.Servings.Int64())
// 		servings = &v
// 	}

// 	return ext.MealPlanEntry{
// 		ID:         m.ID.UUID(),
// 		WeekStart:  m.WeekStart.Time(),
// 		DayOfWeek:  m.DayOfWeek.String(),
// 		MealType:   m.MealType.String(),
// 		RecipeID:   recipeID,
// 		RecipeName: recipeName,
// 		CustomMeal: m.CustomMeal.String(),
// 		Servings:   servings,
// 		Notes:      m.Notes.String(),
// 		CreatedAt:  m.CreatedAt.Time(),
// 	}
// }

// func shoppingListFromModel(m generatedmodels.ModelPublicShoppingLists) ext.ShoppingList {
// 	list := ext.ShoppingList{
// 		ID:        m.ID.UUID(),
// 		WeekStart: m.WeekStart.Time(),
// 		Notes:     m.Notes.String(),
// 		CreatedAt: m.CreatedAt.Time(),
// 		UpdatedAt: m.UpdatedAt.Time(),
// 	}
// 	if err := json.Unmarshal(m.Items, &list.Items); err != nil {
// 		list.Items = []ext.ShoppingItem{}
// 	}
// 	return list
// }

func planFromModel(m generatedmodels.ModelPublicPlans, tags []string) ext.Plan {
	var projectID *int64
	if m.ProjectID.Valid {
		id := m.ProjectID.Int64()
		projectID = &id
	}

	var dueDate *time.Time
	if m.DueDate.Valid {
		t := m.DueDate.Time()
		dueDate = &t
	}

	var completedAt *time.Time
	if m.CompletedAt.Valid {
		t := m.CompletedAt.Time()
		completedAt = &t
	}

	var lastReviewedAt *time.Time
	if m.LastReviewedAt.Valid {
		t := m.LastReviewedAt.Time()
		lastReviewedAt = &t
	}

	var supersedesPlanID *int64
	if m.SupersedesPlanID.Valid {
		id := m.SupersedesPlanID.Int64()
		supersedesPlanID = &id
	}

	return ext.Plan{
		ID:               m.ID.Int64(),
		GUID:             m.GUID.UUID(),
		Title:            m.Title.String(),
		Description:      m.Description.String(),
		Status:           ext.PlanStatus(m.Status.String()),
		Priority:         ext.PlanPriority(m.Priority.String()),
		ProjectID:        projectID,
		Owner:            m.Owner.String(),
		DueDate:          dueDate,
		CompletedAt:      completedAt,
		ReviewedBy:       m.ReviewedBy.String(),
		LastReviewedAt:   lastReviewedAt,
		SupersedesPlanID: supersedesPlanID,
		Tags:             tags,
		CreatedAt:        m.CreatedAt.Time(),
		UpdatedAt:        m.UpdatedAt.Time(),
	}
}

func learningFromModel(m generatedmodels.ModelPublicLearnings, tags []string) ext.Learning {
	var projectID *int64
	if m.ProjectID.Valid {
		id := m.ProjectID.Int64()
		projectID = &id
	}

	var relatedThoughtID *int64
	if m.RelatedThoughtID.Valid {
		id := m.RelatedThoughtID.Int64()
		relatedThoughtID = &id
	}

	var relatedSkillID *int64
	if m.RelatedSkillID.Valid {
		id := m.RelatedSkillID.Int64()
		relatedSkillID = &id
	}

	var duplicateOfLearningID *int64
	if m.DuplicateOfLearningID.Valid {
		id := m.DuplicateOfLearningID.Int64()
		duplicateOfLearningID = &id
	}

	var supersedesLearningID *int64
	if m.SupersedesLearningID.Valid {
		id := m.SupersedesLearningID.Int64()
		supersedesLearningID = &id
	}

	var reviewedBy *string
	if m.ReviewedBy.Valid {
		value := m.ReviewedBy.String()
		reviewedBy = &value
	}

	var reviewedAt *time.Time
	if m.ReviewedAt.Valid {
		t := m.ReviewedAt.Time()
		reviewedAt = &t
	}

	return ext.Learning{
		ID:                    m.ID.Int64(),
		GUID:                  m.GUID.UUID(),
		Summary:               m.Summary.String(),
		Details:               m.Details.String(),
		Category:              m.Category.String(),
		Area:                  m.Area.String(),
		Status:                ext.LearningStatus(m.Status.String()),
		Priority:              ext.LearningPriority(m.Priority.String()),
		Confidence:            ext.LearningEvidenceLevel(m.Confidence.String()),
		ActionRequired:        m.ActionRequired,
		SourceType:            m.SourceType.String(),
		SourceRef:             m.SourceRef.String(),
		ProjectID:             projectID,
		RelatedThoughtID:      relatedThoughtID,
		RelatedSkillID:        relatedSkillID,
		ReviewedBy:            reviewedBy,
		ReviewedAt:            reviewedAt,
		DuplicateOfLearningID: duplicateOfLearningID,
		SupersedesLearningID:  supersedesLearningID,
		Tags:                  tags,
		CreatedAt:             m.CreatedAt.Time(),
		UpdatedAt:             m.UpdatedAt.Time(),
	}
}
