import{and as S,desc as q,eq as l,sql as e}from"drizzle-orm";import{logger as V}from"../../../../../tools/notifiers/logger.js";import{applyPagination as k}from"../../../../../providers/database/pagination/index.js";import{getEffectivePaginationLimit as J}from"../../../../../providers/database/pagination/limit.js";import{applyFilter as P,excludeFieldsFromFilter as z,getAllFilterFieldValues as W}from"../../../../../providers/database/pagination/filter.js";import{entitiesAttributesTable as N}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-attributes-table.js";import{entitiesRelationsTable as K}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{entitiesTable as a}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{createBffEntity as L}from"../../mappers/create-bff-entity.js";import{FIELDS_TO_SELECT_FOR_ENTITY as p,FIELDS_TO_SELECT_FOR_ENTITY_RELATION as G,createEntityFieldsForSelect as D}from"../utils.js";import{buildEntitiesExclusionFilter as B}from"../utils/build-entities-exclusion-filter.js";import{buildRbacFilter as X,buildSubqueryRbacJoinAndFilter as Y}from"../utils/build-rbac-filter.js";import{buildSemanticVersionSortExpr as I}from"../utils/semantic-version-sort.js";const i={entityForKey:"e",baseEntities:"base_entities",pagedEntities:"paged_entities",combinedRelations:"combined_relations",combinedTargetEntities:"combined_target_entities",combinedTargetAttributes:"combined_target_attributes"};class ut{#t;constructor(t){this.#t=t}async getEntitiesWithRelations({paginationParams:t,rbacTeams:r,excludedEntities:n,excludedTypes:o}){const c=W(t.filter,"owners");if(c.length>0)return this.#c(t,c,r,o,n);const E=W(t.filter,"domains");return E.length>0?this.#l(t,E,r,o,n):this.#d(t,r,o,n)}async getEntityWithRelationsByKey({entityKey:t,filter:r,rbacTeams:n,excludedTypes:o,excludedEntities:c}){if(!t||t.trim()==="")return null;const E=r?.revision,u=r?.version,y=E?null:await this.#u(t,u||null),C=u??y?.version,R=E||y?.revision||null,F=B(o,c,"entities"),d=this.#t.client.select(D("entities")).from(a).leftJoin(N,l(a.key,N.entityKey)).where(S(l(a.key,t),X(n,"entities_attributes"),F)).as(i.entityForKey),g=this.#e().as(i.combinedRelations),b=this.#i(o,c).as(i.combinedTargetEntities),$=this.#s().as(i.combinedTargetAttributes),h=this.#t.client.with(d,g,b,$).select({...D(i.entityForKey),domains:this.#n(i.entityForKey,n).as("domains"),owners:this.#r(i.entityForKey,n).as("owners")}).from(d).$dynamic();R?h.where(S(l(e.raw("revision"),R),C?l(e.raw("version"),C):void 0)):(h.where(l(e.raw("is_current"),1)),h.orderBy(e`${I("version")} DESC`,e.raw("revision DESC"))),h.limit(1);const s=await h.get();return s?L(s):null}async#c(t,r,n,o,c){const E=this.#o(n,o,c),u=this.#e(),y=this.#i(o,c),C=u.as(i.combinedRelations),R=y.as(i.combinedTargetEntities),_=this.#s().as(i.combinedTargetAttributes),d=r.map(s=>e`
        EXISTS (
          SELECT 1 FROM (${u}) cr
          WHERE cr.source_key = ${s}
            AND cr.source_to_target_relation = 'owns'
            AND cr.target_key = ${e.raw(`${i.baseEntities}.key`)}
        )
      `),g=d.length===1?d[0]:e`(${e.join(d,e` OR `)})`,T=W(t.filter,"domains");let b=g;if(T.length>0){const s=T.map(m=>e`
          EXISTS (
            SELECT 1 FROM (${u}) cr
            JOIN (${y}) d ON d.key = ${m}
            WHERE d.type = 'domain'
              AND d.is_current = 1
              AND cr.source_key = ${m}
              AND cr.target_key = ${e.raw(`${i.baseEntities}.key`)}
              AND cr.source_to_target_relation = 'hasParts'
          )
        `),f=s.length===1?s[0]:e`(${e.join(s,e` OR `)})`;b=e`(${g} AND ${f})`}const v=z(t.filter,["owners","domains"]),$={...t,filter:v,baseWhereCondition:b},h=this.#t.client.select(p).from(E.as(i.baseEntities)).$dynamic();try{const s=this.#t.client.select(p).from(E.as(i.baseEntities)).$dynamic();k(s,{...$,limit:void 0,skip:void 0,after:void 0,before:void 0});const f=this.#t.client.$count(s),m=J(t);k(h,{...$,limit:m+1});const w=h.as(i.pagedEntities),Q=this.#t.client.with(C,R,_,w).select({...D(i.pagedEntities),domains:this.#n(i.pagedEntities,n).as("domains"),owners:this.#r(i.pagedEntities,n).as("owners")}).from(w),[M,H]=await Promise.all([Q.all(),f]),O=M,j=O.length>m;return{items:O.slice(0,m).map(A=>L(A)).filter(A=>A!==null),hasMore:j,total:H}}catch(s){return V.error("Error getting entities with relations (owner optimized path): "+s.message),{items:[],hasMore:!1,total:0}}}async#l(t,r,n,o,c){const E=this.#o(n,o,c),u=this.#e(),y=this.#i(o,c),C=u.as(i.combinedRelations),R=y.as(i.combinedTargetEntities),_=this.#s().as(i.combinedTargetAttributes),d=r.map(s=>e`
        EXISTS (
          SELECT 1 FROM (${u}) cr
          JOIN (${y}) d ON d.key = ${s}
          WHERE d.type = 'domain'
            AND d.is_current = 1
            AND cr.source_key = ${s}
            AND cr.target_key = ${e.raw(`${i.baseEntities}.key`)}
            AND cr.source_to_target_relation = 'hasParts'
        )
      `),g=d.length===1?d[0]:e`(${e.join(d,e` OR `)})`,T=W(t.filter,"owners");let b=g;if(T.length>0){const s=T.map(m=>e`
          EXISTS (
            SELECT 1 FROM (${u}) cr
            WHERE cr.source_key = ${m}
              AND cr.source_to_target_relation = 'owns'
              AND cr.target_key = ${e.raw(`${i.baseEntities}.key`)}
          )
        `),f=s.length===1?s[0]:e`(${e.join(s,e` OR `)})`;b=e`(${g} AND ${f})`}const v=z(t.filter,["domains","owners"]),$={...t,filter:v,baseWhereCondition:b},h=this.#t.client.select(p).from(E.as(i.baseEntities)).$dynamic();try{const s=this.#t.client.select(p).from(E.as(i.baseEntities)).$dynamic();k(s,{...$,limit:void 0,skip:void 0,after:void 0,before:void 0});const f=this.#t.client.$count(s),m=J(t);k(h,{...$,limit:m+1});const w=h.as(i.pagedEntities),Q=this.#t.client.with(C,R,_,w).select({...D(i.pagedEntities),domains:this.#n(i.pagedEntities,n).as("domains"),owners:this.#r(i.pagedEntities,n).as("owners")}).from(w),[M,H]=await Promise.all([Q.all(),f]),O=M,j=O.length>m;return{items:O.slice(0,m).map(A=>L(A)).filter(A=>A!==null),hasMore:j,total:H}}catch(s){return V.error("Error getting entities with relations (domain optimized path): "+s.message),{items:[],hasMore:!1,total:0}}}async#d(t,r,n,o){const c=this.#o(r,n,o),E=this.#e(),u=this.#i(n,o),y=E.as(i.combinedRelations),C=u.as(i.combinedTargetEntities),F=this.#s().as(i.combinedTargetAttributes),_=this.#t.client.select(p).from(c.as(i.baseEntities)).$dynamic(),{whereCondition:d}=P(_,t.filter);d&&_.where(d);try{const g=this.#t.client.select(p).from(c.as(i.baseEntities)).$dynamic();d&&g.where(d);const T=this.#t.client.$count(g),b=J(t);k(_,{...t,limit:b+1});const v=_.as(i.pagedEntities),$=this.#t.client.with(y,C,F,v).select({...D(i.pagedEntities),domains:this.#n(i.pagedEntities,r).as("domains"),owners:this.#r(i.pagedEntities,r).as("owners")}).from(v),[h,s]=await Promise.all([$.all(),T]),f=h,m=f.length>b;return{items:f.slice(0,b).map(w=>L(w)).filter(w=>w!==null),hasMore:m,total:s}}catch(g){return V.error("Error getting entities with relations (optimized path): "+g.message),{items:[],hasMore:!1,total:0}}}#o(t,r,n){const o=B(r,n,"entities");return this.#t.client.select(D("entities")).from(a).leftJoin(N,l(a.key,N.entityKey)).where(S(l(a.isCurrent,!0),l(a.isDeleted,!1),X(t,"entities_attributes"),o,this.#a("entities")))}#e(){return this.#t.client.select(G).from(K).where(l(K.isDeleted,!1))}#i(t,r){const n=B(t,r,"entities");return this.#t.client.select(p).from(a).where(S(l(a.isCurrent,!0),l(a.isDeleted,!1),n,this.#a("entities")))}async#u(t,r){if(r){const c=await this.#t.client.select({version:a.version,revision:a.revision}).from(a).where(S(l(a.key,t),l(a.version,r))).orderBy(q(a.revision)).limit(1).get();return c?{version:c.version||null,revision:c.revision||null}:null}const n=await this.#t.client.select({version:a.version,revision:a.revision}).from(a).where(S(l(a.key,t),l(a.isCurrent,!0),l(a.isDeleted,!1))).orderBy(e`${I("entities.version")} DESC`,q(a.revision)).limit(1).get();return n?{version:n.version||null,revision:n.revision||null}:null}#a(t){const r=e.raw(`${t}.key`),n=I(`${t}.version`),o=e.raw(`${t}.revision`),c=I("higher.version");return e`
      NOT EXISTS (
        SELECT 1
        FROM entities higher
        WHERE higher.key = ${r}
          AND higher.is_current = 1
          AND COALESCE(higher.is_deleted, 0) = 0
          AND (
            (${c}) > (${n})
            OR (
              (${c}) = (${n})
              AND higher.revision > ${o}
            )
          )
      )
    `}#n(t,r){const{join:n,filter:o}=Y(r,"d.key");return e`
      COALESCE(
        (
          SELECT json_group_array(
            json_object(
              'id', d.id,
              'key', d.key,
              'type', d.type,
              'title', d.title,
              'summary', d.summary,
              'created_at', d.created_at,
              'updated_at', d.updated_at,
              'source', d.source,
              'source_file', d.source_file
            )
          )
          FROM (
            SELECT DISTINCT d.*
            FROM combined_relations er
            JOIN combined_target_entities d ON d.key = er.source_key
            ${n}
            WHERE er.source_to_target_relation = 'hasParts'
              AND er.target_key = ${e.raw(`${t}.key`)}
              AND d.type = 'domain'
              AND d.is_current = 1
              ${o}
              AND CASE 
                WHEN ${e.raw(`${t}.version`)} = '' 
                THEN er.target_version = ''
                ELSE (er.target_version = ${e.raw(`${t}.version`)} OR er.target_version = '')
              END
              AND CASE 
                WHEN ${e.raw(`${t}.revision`)} = '' 
                THEN 1 = 1
                ELSE (er.target_revision <= ${e.raw(`${t}.revision`)} OR er.target_revision = '')
              END
            LIMIT 10
          ) d
        ),
        json_array()
      )
    `}#r(t,r){const{join:n,filter:o}=Y(r,"o.key");return e`
      COALESCE(
        (
          SELECT json_group_array(
            json_object(
              'id', o.id,
              'key', o.key,
              'type', o.type,
              'title', o.title,
              'summary', o.summary,
              'created_at', o.created_at,
              'updated_at', o.updated_at,
              'source', o.source,
              'source_file', o.source_file
            )
          )
          FROM (
            SELECT DISTINCT o.*
            FROM combined_relations er
            JOIN combined_target_entities o ON o.key = er.source_key
            ${n}
            WHERE er.source_to_target_relation = 'owns'
              AND er.target_key = ${e.raw(`${t}.key`)}
              AND o.is_current = 1
              ${o}
              AND CASE 
                WHEN ${e.raw(`${t}.version`)} = '' 
                THEN er.target_version = ''
                ELSE (er.target_version = ${e.raw(`${t}.version`)} OR er.target_version = '')
              END
              AND CASE 
                WHEN ${e.raw(`${t}.revision`)} = '' 
                THEN 1 = 1
                ELSE (er.target_revision <= ${e.raw(`${t}.revision`)} OR er.target_revision = '')
              END
            LIMIT 10
          ) o
        ),
        json_array()
      )
    `}#s(){return this.#t.client.select({entityKey:N.entityKey,rbacTeams:N.rbacTeams}).from(N)}}export{ut as BffEntitiesReadRepository};
