// This script contains ALL relations for the database, used by drizzle-orm
import {
  energyAssessmentDocuments,
  energyAssessmentScenarios,
} from "./energy_assessments";

import { relations } from "drizzle-orm";
import {
  nonInstrusiveSurvey,
  nonIntrusiveSurveyNotes,
  property,
  propertyDetailsEpc,
  propertyTargets,
} from "./property";
import {
  plan,
  planRecommendations,
  recommendation,
  recommendationMaterials,
} from "./recommendations";
import { material } from "./materials";
import { portfolio, portfolioUsers } from "./portfolio";
import { user } from "./users";
import { fundingPackage, fundingPackageMeasures } from "./funding";

// Define the other side of the one to many relation between a property and its recomendations
export const recommendationsRelations = relations(
  recommendation,
  ({ one, many }) => ({
    property: one(property, {
      fields: [recommendation.propertyId],
      references: [property.id],
    }),
    recommendationMaterials: many(recommendationMaterials),
    planRecommendations: many(planRecommendations),
  })
);

// We construct a relationship between a recommendation and recommendationMaterials
// On recommendationMaterial will map to a single recommendation

// Define the relationships for the material table
export const materialRelations = relations(material, ({ many }) => ({
  recommendationMaterials: many(recommendationMaterials),
}));

// Define the relationships for the recommendationMaterials table
export const recommendationMaterialsRelations = relations(
  recommendationMaterials,
  ({ one }) => ({
    recommendation: one(recommendation, {
      fields: [recommendationMaterials.recommendationId],
      references: [recommendation.id],
    }),
    material: one(material, {
      fields: [recommendationMaterials.materialId],
      references: [material.id],
    }),
  })
);

// create a one to many relation to map a plan to the details in the underlying recommendation
// create a many to many map from a plan to a recommendation
// A recommendation can be in multiple plans and therefore we have a many to many relationship between
// plan and recommendations. This relationship is facilitated by the planRecommendations table.
// We also need to be able to get from a plan to its property

export const planRelations = relations(plan, ({ one, many }) => ({
  property: one(property, {
    fields: [plan.propertyId],
    references: [property.id],
  }),
  planRecommendations: many(planRecommendations),
  fundingPackage: one(fundingPackage, {
    fields: [plan.id],
    references: [fundingPackage.planId],
  }),
}));

export const planRecommendationsRelations = relations(
  planRecommendations,
  ({ one }) => ({
    plan: one(plan, {
      fields: [planRecommendations.planId],
      references: [plan.id],
    }),
    recommendation: one(recommendation, {
      fields: [planRecommendations.recommendationId],
      references: [recommendation.id],
    }),
  })
);

// one to one relationship between property and propertyTargets, and also to the recommendations table
// We also relate a property to it's many plans, from which we can take the default
export const propertyRelations = relations(property, ({ one, many }) => ({
  target: one(propertyTargets, {
    fields: [property.id],
    references: [propertyTargets.propertyId],
  }),
  recommendations: many(recommendation),
  detailsEpc: one(propertyDetailsEpc, {
    fields: [property.id],
    references: [propertyDetailsEpc.propertyId],
  }),
  plans: many(plan),
}));

// We have a many to many relationship between users and portfolios
// One user can have many portfolios, and one portfolio can have many users
// We use the Dizzle relational queries pattern to facilitate this

// Define relation from users to portfolios
export const usersToPortfolioRelations = relations(user, ({ many }) => ({
  portfolios: many(portfolio),
}));

// Define relation from portfolios to users
export const portfolioToUsersRelations = relations(portfolio, ({ many }) => ({
  users: many(user),
}));

// Define relation from portfolioUsers to portfolios (we can have many users to a portfolio)
// export const portfolioUsersToPortfolioRelations = relations(
//   portfolioUsers,
//   ({ many }) => ({
//     portfolio: many(portfolio),
//   })
// );
export const portfolioUsersToPortfolioRelations = relations(
  portfolioUsers,
  ({ one }) => ({
    portfolio: one(portfolio, {
      fields: [portfolioUsers.portfolioId], // Ensure the correct foreign key is specified
      references: [portfolio.id],
    }),
  })
);

// Define a relation from non-intrusive survey to non-intrusive survey notes
// One survey can have many notes
export const nonInstrusiveSurveyRelations = relations(
  nonInstrusiveSurvey,
  ({ many }) => ({
    notes: many(nonIntrusiveSurveyNotes),
  })
);

export const nonIntrusiveSurveyNotesRelations = relations(
  nonIntrusiveSurveyNotes,
  ({ one }) => ({
    survey: one(nonInstrusiveSurvey, {
      fields: [nonIntrusiveSurveyNotes.surveyId],
      references: [nonInstrusiveSurvey.id],
    }),
  })
);

// Define a relation from a EnergyAssessmentDocument to EnergyAssessmentScenario. This is a many to one
export const energyAssessmentDocumentsRelations = relations(
  energyAssessmentDocuments,
  ({ one }) => ({
    scenario: one(energyAssessmentScenarios, {
      fields: [energyAssessmentDocuments.scenarioId],
      references: [energyAssessmentScenarios.id],
    }),
  })
);

// Relation from a funding package to funding package measures
// Define a relation from a EnergyAssessmentDocument to EnergyAssessmentScenario. This is a many to one

// funding package links to multiple funding package measures. We also link to a plan
export const fundingPackageRelations = relations(
  fundingPackage,
  ({ one, many }) => ({
    plan: one(plan, {
      fields: [fundingPackage.planId],
      references: [plan.id],
    }),
    fundingPackageMeasures: many(fundingPackageMeasures),
  })
);

// funding package measures belong to a funding package
export const fundingPackageMeasuresRelations = relations(
  fundingPackageMeasures,
  ({ one }) => ({
    fundingPackage: one(fundingPackage, {
      fields: [fundingPackageMeasures.fundingPackageId],
      references: [fundingPackage.id],
    }),
  })
);
