import { Association, Attributes, BelongsToGetAssociationMixin, BelongsToManyAddAssociationMixin, BelongsToManyAssociation, BelongsToManyCreateAssociationMixin, BelongsToManyGetAssociationsMixin, BelongsToManyRemoveAssociationMixin, BelongsToManySetAssociationsMixin, CreationOptional, DataTypes, ForeignKey, InferAttributes, InferCreationAttributes, Model, NonAttribute, Sequelize } from "@sequelize/core";import { User } from "./User";

import { SqliteDialect } from '@sequelize/sqlite3';
import { Attribute, AutoIncrement, BelongsTo, BelongsToMany, CreatedAt, Default, HasMany, NotNull, PrimaryKey, Unique, UpdatedAt } from "@sequelize/core/decorators-legacy";
import { Tag } from "./Tag";
import { PostTag } from "./PostTag";
import { Project } from "./Project";
import { Attachment } from "./Attachment";
import { Bucket } from "./Bucket";
import { UUID } from "crypto";

export type PostAttributes = InferAttributes<Post>;

export type PostCreationAttributes = InferCreationAttributes<Post>;

export type PostAttributesWithBuckets = PostAttributes & {
    buckets:Attributes<Bucket>[]
}

export class Post extends Model<PostAttributes, PostCreationAttributes> {
    

    // Attributes
    @Attribute(DataTypes.INTEGER)
    @PrimaryKey
    @AutoIncrement
    @Unique
    declare id: CreationOptional<number>;
    
    @Attribute(DataTypes.STRING)
    declare title:string;
    @Attribute(DataTypes.STRING)
    declare content:string;
    @Attribute(DataTypes.STRING)
    declare description?:CreationOptional<string>;
    
    // Date thingies
    @CreatedAt
    declare createdAt: CreationOptional<Date>;
    @UpdatedAt
    declare updatedAt: CreationOptional<Date>;

    

    // Associatoins
    @Attribute(DataTypes.INTEGER)
    @NotNull
    declare user_id:ForeignKey<User['id']>;

    @Attribute(DataTypes.INTEGER)
    declare project_id:CreationOptional<ForeignKey<User['id']>>;

    @BelongsTo(()=>User, { foreignKey: 'user_id', inverse: { type: 'hasMany', as: 'posts' } })
    declare user:NonAttribute<User>;

    @BelongsTo(()=>Project, { foreignKey:'project_id', foreignKeyConstraints: false, inverse: { type: 'hasMany', as: 'posts' } })
    declare project:CreationOptional<Project>;

    @BelongsToMany(()=>Tag, { through: { model: ()=>PostTag, unique: false}, inverse: {as: 'taggedPosts'} })
    declare postTags?:NonAttribute<Tag[]>;

    
    @BelongsToMany(()=>Bucket,{through: {model:'PostBucket'}, foreignKeyConstraints: false, throughAssociations: {
        fromSource: 'postBucketBuckets',
        toSource: 'post',
        fromTarget: 'postBucketPosts',
        toTarget: 'PostBucket',
    }, inverse:{as: 'posts'}, foreignKey: {name: 'postId', unique: false}, otherKey: 'bucketId', })
    declare buckets?:NonAttribute<Bucket[]>;

    



    declare static associations: {
        user: Association<User, Post>;
        project: Association<Project, Post>;
        buckets: Association<Bucket, Post>
        postTags: Association<Tag, Post>;
    };

    declare getUser: BelongsToGetAssociationMixin<User>;
    declare getBuckets: BelongsToManyGetAssociationsMixin<Bucket>;
    declare setBuckets: BelongsToManySetAssociationsMixin<Bucket,Bucket['id']>;
    declare addBucket: BelongsToManyAddAssociationMixin<Bucket,Bucket['id']>;
    declare addBuckets: BelongsToManyAddAssociationMixin<Bucket,Bucket['id']>;
    declare removeBucket: BelongsToManyRemoveAssociationMixin<Bucket,Bucket['id']>;
    declare removeBuckets: BelongsToManyRemoveAssociationMixin<Bucket,Bucket['id']>;
    declare createBucket:  BelongsToManyCreateAssociationMixin<Bucket>;
}

export class PostBucket extends Model<InferAttributes<PostBucket>, InferCreationAttributes<PostBucket>> {
    declare postId: number;
    declare bucketId: UUID;

    declare post?:NonAttribute<Post>
    declare bucket?:NonAttribute<Bucket>
}

export function addPostScopes(){
    Post.addScope('withProject', {include: [{association: Post.associations.project}]})
}
