import type { Operation } from '@model/relational';
import type { CountAllOperation, NoOperation } from '@model/relational';
import type { Attribute } from '@datafinder/attribute';
import type { FinderResult } from '@datafinder/runner';
import type { ExistsOperation, NotExistsOperation } from '@model/relational';
{% set attr_types = get_used_attr_types(rcm) %}
{% if attr_types %}
import type { {{attr_types | join(', ')}} } from '@datafinder/typed-attributes';
{% endif %}
{% set ns = namespace(seen_base=[]) %}
{% for rpm in rcm.property_mappings %}
{% if not is_primitive(rpm.property) and rpm.property.type.name != rcm.clazz.name and rpm.property.type.name not in ns.seen_base %}
import type { {{rpm.property.type.name}}RelatedFinderBase, {{rpm.property.type.name}}Filter } from '{{class_module_map_base[rpm.property.type.name]}}Base';
{% set ns.seen_base = ns.seen_base + [rpm.property.type.name] %}
{% endif %}
{% endfor %}
{% set ns2 = namespace(seen_rev_base=[]) %}
{% for source_rcm, rpm, assoc, reverse_name in reverse_assocs %}
{% if source_rcm.clazz.name not in ns2.seen_rev_base and source_rcm.clazz.name != rcm.clazz.name %}
import type { {{source_rcm.clazz.name}}RelatedFinderBase, {{source_rcm.clazz.name}}Filter } from '{{class_module_map_base[source_rcm.clazz.name]}}Base';
{% set ns2.seen_rev_base = ns2.seen_rev_base + [source_rcm.clazz.name] %}
{% endif %}
{% endfor %}

/** Property-equality filters accepted by the accessors that join to {{rcm.clazz.name}}, keyed by property id. */
export interface {{rcm.clazz.name}}Filter {
{% for rpm in rcm.property_mappings %}
{% if is_primitive(rpm.property) %}
  {{rpm.property.id}}?: {{filter_ts_type(rpm.property)}};
{% endif %}
{% endfor %}
}

{% set _class_doc = get_doc(rcm.clazz) %}
{% if _class_doc %}
/** {{_class_doc}} */
{% endif %}
export abstract class {{rcm.clazz.name}}RelatedFinderBase {
{% for rpm in rcm.property_mappings %}
{% if is_primitive(rpm.property) %}
  {{prop_jsdoc(rpm.property)}}
  abstract {{to_ts_name(rpm.property)}}(): {{rpm.property.type.name}}Attribute;
{% else %}
  {{prop_jsdoc(rpm.property)}}
  abstract {{to_ts_name(rpm.property)}}(filter?: {{rpm.property.type.name}}Filter): {{rpm.property.type.name}}RelatedFinderBase;
{% endif %}
{% endfor %}
{% for source_rcm, rpm, assoc, reverse_name in reverse_assocs %}
  abstract {{reverse_name}}(filter?: {{source_rcm.clazz.name}}Filter): {{source_rcm.clazz.name}}RelatedFinderBase;
{% endfor %}
  /** Filter to rows that have a matching {{rcm.clazz.name}} through this join. */
  abstract exists(): ExistsOperation;
  /** Filter to rows that have no matching {{rcm.clazz.name}} through this join. */
  abstract notExists(): NotExistsOperation;
}

{% if _class_doc %}
/** {{_class_doc}} */
{% endif %}
export abstract class {{rcm.clazz.name}}FinderBase {
{% for rpm in rcm.property_mappings %}
{% if is_primitive(rpm.property) %}
  {{prop_jsdoc(rpm.property)}}
  abstract {{to_ts_name(rpm.property)}}(): {{rpm.property.type.name}}Attribute;
{% else %}
  {{prop_jsdoc(rpm.property)}}
  abstract {{to_ts_name(rpm.property)}}(filter?: {{rpm.property.type.name}}Filter): {{rpm.property.type.name}}RelatedFinderBase;
{% endif %}
{% endfor %}
{% for source_rcm, rpm, assoc, reverse_name in reverse_assocs %}
  abstract {{reverse_name}}(filter?: {{source_rcm.clazz.name}}Filter): {{source_rcm.clazz.name}}RelatedFinderBase;
{% endfor %}
  abstract count(): CountAllOperation;
  abstract findAll(
    businessDate: Date | string | null,
    processingValidAt: Date | string | null,
    displayColumns: (Attribute | import('@model/relational').RelationalOperationElement)[],
    filterOp?: Operation,
  ): FinderResult;
{% if rcm.milestone_mapping and (has_bitemporal(rcm.milestone_mapping) or has_business_date_and_processing(rcm.milestone_mapping) or has_uni_business_temporal(rcm.milestone_mapping)) %}
  abstract findForDateRange(
    businessDateFrom: Date | string,
    businessDateTo: Date | string,
    processingValidAt: Date | string,
    displayColumns: (Attribute | import('@model/relational').RelationalOperationElement)[],
    filterOp?: Operation,
  ): FinderResult;
{% endif %}
}
